📄 log.c
字号:
{ value.data = propval; value.len = strlen(propval); } SVN_ERR(svn_wc__wcprop_set(propname, propval ? &value : NULL, path, loggy->adm_access, FALSE, loggy->pool)); loggy->wcprops_modified = TRUE; return SVN_NO_ERROR;}static svn_error_t *log_do_upgrade_format(struct log_runner *loggy, const char **atts){ const char *fmtstr = svn_xml_get_attr_value(SVN_WC__LOG_ATTR_FORMAT, atts); int fmt; const char *path = svn_wc__adm_path(svn_wc_adm_access_path(loggy->adm_access), FALSE, loggy->pool, SVN_WC__ADM_FORMAT, NULL); if (! fmtstr || (fmt = atoi(fmtstr)) == 0) return svn_error_create(pick_error_code(loggy), NULL, _("Invalid 'format' attribute")); /* Update the .svn/format file right away. */ SVN_ERR(svn_io_write_version_file(path, fmt, loggy->pool)); /* The nice thing is that, just by setting this flag, the entries file will be rewritten in the desired format. */ loggy->entries_modified = TRUE; /* Reading the entries file will support old formats, even if this number is updated. */ svn_wc__adm_set_wc_format(loggy->adm_access, fmt); return SVN_NO_ERROR;}static voidstart_handler(void *userData, const char *eltname, const char **atts){ svn_error_t *err = SVN_NO_ERROR; struct log_runner *loggy = userData; /* Most elements use the `name' attribute, so grab it now. */ const char *name = svn_xml_get_attr_value(SVN_WC__LOG_ATTR_NAME, atts); /* Clear the per-log-item pool. */ svn_pool_clear(loggy->pool); if (strcmp(eltname, "wc-log") == 0) /* ignore expat pacifier */ return; else if (! name && strcmp(eltname, SVN_WC__LOG_UPGRADE_FORMAT) != 0) { signal_error (loggy, svn_error_createf (pick_error_code(loggy), NULL, _("Log entry missing 'name' attribute (entry '%s' " "for directory '%s')"), eltname, svn_path_local_style(svn_wc_adm_access_path(loggy->adm_access), loggy->pool))); return; } /* Increment the top-level element count before processing any commands. */ loggy->count += 1; /* Dispatch. */ if (strcmp(eltname, SVN_WC__LOG_MODIFY_ENTRY) == 0) { err = log_do_modify_entry(loggy, name, atts); } else if (strcmp(eltname, SVN_WC__LOG_DELETE_LOCK) == 0) { err = log_do_delete_lock(loggy, name); } else if (strcmp(eltname, SVN_WC__LOG_DELETE_ENTRY) == 0) { err = log_do_delete_entry(loggy, name); } else if (strcmp(eltname, SVN_WC__LOG_COMMITTED) == 0) { err = log_do_committed(loggy, name, atts); } else if (strcmp(eltname, SVN_WC__LOG_MODIFY_WCPROP) == 0) { err = log_do_modify_wcprop(loggy, name, atts); } else if (strcmp(eltname, SVN_WC__LOG_RM) == 0) { err = log_do_rm(loggy, name); } else if (strcmp(eltname, SVN_WC__LOG_MERGE) == 0) { err = log_do_merge(loggy, name, atts); } else if (strcmp(eltname, SVN_WC__LOG_MV) == 0) { err = log_do_file_xfer(loggy, name, svn_wc__xfer_mv, atts); } else if (strcmp(eltname, SVN_WC__LOG_CP) == 0) { err = log_do_file_xfer(loggy, name, svn_wc__xfer_cp, atts); } else if (strcmp(eltname, SVN_WC__LOG_CP_AND_TRANSLATE) == 0) { err = log_do_file_xfer(loggy, name,svn_wc__xfer_cp_and_translate, atts); } else if (strcmp(eltname, SVN_WC__LOG_CP_AND_DETRANSLATE) == 0) { err = log_do_file_xfer(loggy, name,svn_wc__xfer_cp_and_detranslate, atts); } else if (strcmp(eltname, SVN_WC__LOG_APPEND) == 0) { err = log_do_file_xfer(loggy, name, svn_wc__xfer_append, atts); } else if (strcmp(eltname, SVN_WC__LOG_READONLY) == 0) { err = log_do_file_readonly(loggy, name); } else if (strcmp(eltname, SVN_WC__LOG_MAYBE_READONLY) == 0) { err = log_do_file_maybe_readonly(loggy, name); } else if (strcmp(eltname, SVN_WC__LOG_MAYBE_EXECUTABLE) == 0) { err = log_do_file_maybe_executable(loggy, name); } else if (strcmp(eltname, SVN_WC__LOG_SET_TIMESTAMP) == 0) { err = log_do_file_timestamp(loggy, name, atts); } else if (strcmp(eltname, SVN_WC__LOG_UPGRADE_FORMAT) == 0) { err = log_do_upgrade_format(loggy, atts); } else { signal_error (loggy, svn_error_createf (pick_error_code(loggy), NULL, _("Unrecognized logfile element '%s' in '%s'"), eltname, svn_path_local_style(svn_wc_adm_access_path(loggy->adm_access), loggy->pool))); return; } if (err) signal_error (loggy, svn_error_createf (pick_error_code(loggy), err, _("Error processing command '%s' in '%s'"), eltname, svn_path_local_style(svn_wc_adm_access_path(loggy->adm_access), loggy->pool))); return;}/* Process the "KILLME" file in ADM_ACCESS */static svn_error_t *handle_killme(svn_wc_adm_access_t *adm_access, svn_cancel_func_t cancel_func, void *cancel_baton, apr_pool_t *pool){ const svn_wc_entry_t *thisdir_entry, *parent_entry; svn_wc_entry_t tmp_entry; svn_error_t *err; SVN_ERR(svn_wc_entry(&thisdir_entry, svn_wc_adm_access_path(adm_access), adm_access, FALSE, pool)); /* Blow away the entire directory, and all those below it too. */ err = svn_wc_remove_from_revision_control(adm_access, SVN_WC_ENTRY_THIS_DIR, TRUE, /* destroy */ FALSE, /* no instant err */ cancel_func, cancel_baton, pool); if (err && err->apr_err != SVN_ERR_WC_LEFT_LOCAL_MOD) return err; svn_error_clear(err); /* If revnum of this dir is greater than parent's revnum, then recreate 'deleted' entry in parent. */ { const char *parent, *bname; svn_wc_adm_access_t *parent_access; svn_path_split(svn_wc_adm_access_path(adm_access), &parent, &bname, pool); SVN_ERR(svn_wc_adm_retrieve(&parent_access, adm_access, parent, pool)); SVN_ERR(svn_wc_entry(&parent_entry, parent, parent_access, FALSE, pool)); if (thisdir_entry->revision > parent_entry->revision) { tmp_entry.kind = svn_node_dir; tmp_entry.deleted = TRUE; tmp_entry.revision = thisdir_entry->revision; SVN_ERR(svn_wc__entry_modify(parent_access, bname, &tmp_entry, SVN_WC__ENTRY_MODIFY_REVISION | SVN_WC__ENTRY_MODIFY_KIND | SVN_WC__ENTRY_MODIFY_DELETED, TRUE, pool)); } } return SVN_NO_ERROR;}/*** Using the parser to run the log file. ***//* Determine the log file that should be used for a given number. */const char *svn_wc__logfile_path(int log_number, apr_pool_t *pool){ return apr_psprintf(pool, SVN_WC__ADM_LOG "%s", (log_number == 0) ? "" : apr_psprintf(pool, ".%d", log_number));}/* Run a series of log-instructions from a memory block of length BUF_LEN at BUF. RERUN and DIFF3_CMD are passed in the log baton to the log runner callbacks. Allocations are done in POOL.*/static svn_error_t *run_log_from_memory(svn_wc_adm_access_t *adm_access, const char *buf, apr_size_t buf_len, svn_boolean_t rerun, const char *diff3_cmd, apr_pool_t *pool){ struct log_runner *loggy; svn_xml_parser_t *parser; /* kff todo: use the tag-making functions here, now. */ const char *log_start = "<wc-log xmlns=\"http://subversion.tigris.org/xmlns\">\n"; const char *log_end = "</wc-log>\n"; loggy = apr_pcalloc(pool, sizeof(*loggy)); loggy->adm_access = adm_access; loggy->pool = svn_pool_create(pool); loggy->parser = svn_xml_make_parser(loggy, start_handler, NULL, NULL, pool); loggy->entries_modified = FALSE; loggy->wcprops_modified = FALSE; loggy->rerun = rerun; loggy->diff3_cmd = diff3_cmd; loggy->count = 0; parser = loggy->parser; /* Expat wants everything wrapped in a top-level form, so start with a ghost open tag. */ SVN_ERR(svn_xml_parse(parser, log_start, strlen(log_start), 0)); SVN_ERR(svn_xml_parse(parser, buf, buf_len, 0)); /* Pacify Expat with a pointless closing element tag. */ SVN_ERR(svn_xml_parse(parser, log_end, strlen(log_end), 1)); return SVN_NO_ERROR;}/* Run a sequence of log files. */static svn_error_t *run_log(svn_wc_adm_access_t *adm_access, svn_boolean_t rerun, const char *diff3_cmd, apr_pool_t *pool){ svn_error_t *err, *err2; svn_xml_parser_t *parser; struct log_runner *loggy = apr_pcalloc(pool, sizeof(*loggy)); char *buf = apr_palloc(pool, SVN__STREAM_CHUNK_SIZE); apr_size_t buf_len; apr_file_t *f = NULL; const char *logfile_path; int log_number; apr_pool_t *iterpool = svn_pool_create(pool); /* kff todo: use the tag-making functions here, now. */ const char *log_start = "<wc-log xmlns=\"http://subversion.tigris.org/xmlns\">\n"; const char *log_end = "</wc-log>\n"; /* #define RERUN_LOG_FILES to test that rerunning log files works */#ifdef RERUN_LOG_FILES int rerun_counter = 2; rerun:#endif parser = svn_xml_make_parser(loggy, start_handler, NULL, NULL, pool); loggy->adm_access = adm_access; loggy->pool = svn_pool_create(pool); loggy->parser = parser; loggy->entries_modified = FALSE; loggy->wcprops_modified = FALSE; loggy->rerun = rerun; loggy->diff3_cmd = diff3_cmd; loggy->count = 0; /* Expat wants everything wrapped in a top-level form, so start with a ghost open tag. */ SVN_ERR(svn_xml_parse(parser, log_start, strlen(log_start), 0)); for (log_number = 0; ; log_number++) { svn_pool_clear(iterpool); logfile_path = svn_wc__logfile_path(log_number, iterpool); /* Parse the log file's contents. */ err = svn_wc__open_adm_file(&f, svn_wc_adm_access_path(adm_access), logfile_path, APR_READ, iterpool); if (err) { if (APR_STATUS_IS_ENOENT(err->apr_err)) { svn_error_clear(err); break; } else { SVN_ERR_W(err, _("Couldn't open log")); } } do { buf_len = SVN__STREAM_CHUNK_SIZE; err = svn_io_file_read(f, buf, &buf_len, iterpool); if (err && !APR_STATUS_IS_EOF(err->apr_err)) return svn_error_createf (err->apr_err, err, _("Error reading administrative log file in '%s'"), svn_path_local_style(svn_wc_adm_access_path(adm_access), iterpool)); err2 = svn_xml_parse(parser, buf, buf_len, 0); if (err2) { if (err) svn_error_clear(err); SVN_ERR(err2); } } while (! err); svn_error_clear(err); SVN_ERR(svn_io_file_close(f, iterpool)); } /* Pacify Expat with a pointless closing element tag. */ SVN_ERR(svn_xml_parse(parser, log_end, strlen(log_end), 1)); svn_xml_free_parser(parser);#ifdef RERUN_LOG_FILES rerun = TRUE; if (--rerun_counter) goto rerun;#endif if (loggy->entries_modified == TRUE) { apr_hash_t *entries; SVN_ERR(svn_wc_entries_read(&entries, loggy->adm_access, TRUE, pool)); SVN_ERR(svn_wc__entries_write(entries, loggy->adm_access, pool)); } if (loggy->wcprops_modified) SVN_ERR(svn_wc__wcprops_
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -