📄 log.c
字号:
const char *name, svn_boolean_t remove_executable, svn_boolean_t remove_read_only, apr_pool_t *pool){ const char *filepath; const char *tmp_text_base; svn_node_kind_t kind; svn_boolean_t same, did_set; const char *tmp_wfile; svn_boolean_t special; /* start off assuming that the working file isn't touched. */ *overwrote_working = FALSE; filepath = svn_path_join(svn_wc_adm_access_path(adm_access), name, pool); /* In the commit, newlines and keywords may have been * canonicalized and/or contracted... Or they may not have * been. It's kind of hard to know. Here's how we find out: * * 1. Make a translated tmp copy of the committed text base. * Or, if no committed text base exists (the commit must have * been a propchange only), make a translated tmp copy of the * working file. * 2. Compare the translated tmpfile to the working file. * 3. If different, copy the tmpfile over working file. * * This means we only rewrite the working file if we absolutely * have to, which is good because it avoids changing the file's * timestamp unless necessary, so editors aren't tempted to * reread the file if they don't really need to. */ /* Is there a tmp_text_base that needs to be installed? */ tmp_text_base = svn_wc__text_base_path(filepath, 1, pool); SVN_ERR(svn_io_check_path(tmp_text_base, &kind, pool)); { const char *tmp = (kind == svn_node_file) ? tmp_text_base : filepath; SVN_ERR(svn_wc_translated_file2(&tmp_wfile, tmp, filepath, adm_access, SVN_WC_TRANSLATE_FROM_NF, pool)); /* If the translation is a no-op, the text base and the working copy * file contain the same content, because we use the same props here * as were used to detranslate from working file to text base. * * In that case: don't replace the working file, but make sure * it has the right executable and read_write attributes set. */ SVN_ERR(svn_wc__get_special(&special, filepath, adm_access, pool)); if (! special && tmp != tmp_wfile) SVN_ERR(svn_io_files_contents_same_p(&same, tmp_wfile, filepath, pool)); else same = TRUE; } if (! same) { SVN_ERR(svn_io_file_rename(tmp_wfile, filepath, pool)); *overwrote_working = TRUE; } if (remove_executable) { /* No need to chmod -x on a new file: new files don't have it. */ if (same) SVN_ERR(svn_io_set_file_executable(filepath, FALSE, /* chmod -x */ FALSE, pool)); *overwrote_working = TRUE; /* entry needs wc-file's timestamp */ } else { /* Set the working file's execute bit if props dictate. */ SVN_ERR(svn_wc__maybe_set_executable(&did_set, filepath, adm_access, pool)); if (did_set) /* okay, so we didn't -overwrite- the working file, but we changed its timestamp, which is the point of returning this flag. :-) */ *overwrote_working = TRUE; } if (remove_read_only) { /* No need to make a new file read_write: new files already are. */ if (same) SVN_ERR(svn_io_set_file_read_write(filepath, FALSE, pool)); *overwrote_working = TRUE; /* entry needs wc-file's timestamp */ } else { SVN_ERR(svn_wc__maybe_set_read_only(&did_set, filepath, adm_access, pool)); if (did_set) /* okay, so we didn't -overwrite- the working file, but we changed its timestamp, which is the point of returning this flag. :-) */ *overwrote_working = TRUE; } /* Install the new text base if one is waiting. */ if (kind == svn_node_file) /* tmp_text_base exists */ SVN_ERR(svn_wc__sync_text_base(filepath, pool)); return SVN_NO_ERROR;}/* Sometimes, documentation would only confuse matters. */static apr_status_tpick_error_code(struct log_runner *loggy){ if (loggy->count <= 1) return SVN_ERR_WC_BAD_ADM_LOG_START; else return SVN_ERR_WC_BAD_ADM_LOG;}static voidsignal_error(struct log_runner *loggy, svn_error_t *err){ svn_xml_signal_bailout (svn_error_createf(pick_error_code(loggy), err, _("In directory '%s'"), svn_path_local_style(svn_wc_adm_access_path (loggy->adm_access), loggy->pool)), loggy->parser);}/*** Dispatch on the xml opening tag. ***/static svn_error_t *log_do_merge(struct log_runner *loggy, const char *name, const char **atts){ const char *left, *right; const char *left_label, *right_label, *target_label; enum svn_wc_merge_outcome_t merge_outcome; svn_stringbuf_t *log_accum = svn_stringbuf_create("", loggy->pool); svn_error_t *err; /* NAME is the basename of our merge_target. Pull out LEFT and RIGHT. */ left = svn_xml_get_attr_value(SVN_WC__LOG_ATTR_ARG_1, atts); if (! left) return svn_error_createf(pick_error_code(loggy), NULL, _("Missing 'left' attribute in '%s'"), svn_path_local_style (svn_wc_adm_access_path(loggy->adm_access), loggy->pool)); right = svn_xml_get_attr_value(SVN_WC__LOG_ATTR_ARG_2, atts); if (! right) return svn_error_createf(pick_error_code(loggy), NULL, _("Missing 'right' attribute in '%s'"), svn_path_local_style (svn_wc_adm_access_path(loggy->adm_access), loggy->pool)); /* Grab all three labels too. If non-existent, we'll end up passing NULLs to svn_wc_merge, which is fine -- it will use default labels. */ left_label = svn_xml_get_attr_value(SVN_WC__LOG_ATTR_ARG_3, atts); right_label = svn_xml_get_attr_value(SVN_WC__LOG_ATTR_ARG_4, atts); target_label = svn_xml_get_attr_value(SVN_WC__LOG_ATTR_ARG_5, atts); /* Convert the 3 basenames into full paths. */ left = svn_path_join(svn_wc_adm_access_path(loggy->adm_access), left, loggy->pool); right = svn_path_join(svn_wc_adm_access_path(loggy->adm_access), right, loggy->pool); name = svn_path_join(svn_wc_adm_access_path(loggy->adm_access), name, loggy->pool); /* Now do the merge with our full paths. */ err = svn_wc__merge_internal(&log_accum, &merge_outcome, left, right, name, loggy->adm_access, left_label, right_label, target_label, FALSE, loggy->diff3_cmd, NULL, loggy->pool); if (err && loggy->rerun && APR_STATUS_IS_ENOENT(err->apr_err)) { svn_error_clear(err); return SVN_NO_ERROR; } else if (err) return err; err = run_log_from_memory(loggy->adm_access, log_accum->data, log_accum->len, loggy->rerun, loggy->diff3_cmd, loggy->pool); if (err && loggy->rerun && APR_STATUS_IS_ENOENT(err->apr_err)) { svn_error_clear(err); return SVN_NO_ERROR; } else return err;}static svn_error_t *log_do_file_xfer(struct log_runner *loggy, const char *name, enum svn_wc__xfer_action action, const char **atts){ svn_error_t *err; const char *dest = NULL; const char *versioned; svn_boolean_t special_only; /* We have the name (src), and the destination is absolutely required. */ dest = svn_xml_get_attr_value(SVN_WC__LOG_ATTR_DEST, atts); special_only = svn_xml_get_attr_value(SVN_WC__LOG_ATTR_ARG_1, atts) != NULL; versioned = svn_xml_get_attr_value(SVN_WC__LOG_ATTR_ARG_2, atts); if (! dest) return svn_error_createf(pick_error_code(loggy), NULL, _("Missing 'dest' attribute in '%s'"), svn_path_local_style (svn_wc_adm_access_path(loggy->adm_access), loggy->pool)); err = file_xfer_under_path(loggy->adm_access, name, dest, versioned, action, special_only, loggy->rerun, loggy->pool); if (err) signal_error(loggy, err); return SVN_NO_ERROR;}/* Make file NAME in log's CWD readonly */static svn_error_t *log_do_file_readonly(struct log_runner *loggy, const char *name){ svn_error_t *err; const char *full_path = svn_path_join(svn_wc_adm_access_path(loggy->adm_access), name, loggy->pool); err = svn_io_set_file_read_only(full_path, FALSE, loggy->pool); if (err && loggy->rerun && APR_STATUS_IS_ENOENT(err->apr_err)) { svn_error_clear(err); return SVN_NO_ERROR; } else return err;}/* Maybe make file NAME in log's CWD executable */static svn_error_t *log_do_file_maybe_executable(struct log_runner *loggy, const char *name){ const char *full_path = svn_path_join(svn_wc_adm_access_path(loggy->adm_access), name, loggy->pool); SVN_ERR(svn_wc__maybe_set_executable(NULL, full_path, loggy->adm_access, loggy->pool)); return SVN_NO_ERROR;}/* Maybe make file NAME in log's CWD readonly */static svn_error_t *log_do_file_maybe_readonly(struct log_runner *loggy, const char *name){ const char *full_path = svn_path_join(svn_wc_adm_access_path(loggy->adm_access), name, loggy->pool); SVN_ERR(svn_wc__maybe_set_read_only(NULL, full_path, loggy->adm_access, loggy->pool)); return SVN_NO_ERROR;}/* Set file NAME in log's CWD to timestamp value in ATTS. */static svn_error_t *log_do_file_timestamp(struct log_runner *loggy, const char *name, const char **atts){ apr_time_t timestamp; svn_node_kind_t kind; const char *full_path = svn_path_join(svn_wc_adm_access_path(loggy->adm_access), name, loggy->pool); const char *timestamp_string = svn_xml_get_attr_value(SVN_WC__LOG_ATTR_TIMESTAMP, atts); svn_boolean_t is_special; if (! timestamp_string) return svn_error_createf(pick_error_code(loggy), NULL, _("Missing 'timestamp' attribute in '%s'"), svn_path_local_style (svn_wc_adm_access_path(loggy->adm_access), loggy->pool)); /* Do not set the timestamp on special files. */ SVN_ERR(svn_io_check_special_path(full_path, &kind, &is_special, loggy->pool)); if (! is_special) { SVN_ERR(svn_time_from_cstring(×tamp, timestamp_string, loggy->pool)); SVN_ERR(svn_io_set_file_affected_time(timestamp, full_path, loggy->pool)); } return SVN_NO_ERROR;}/* Remove file NAME in log's CWD. */static svn_error_t *log_do_rm(struct log_runner *loggy, const char *name){ const char *full_path = svn_path_join(svn_wc_adm_access_path(loggy->adm_access), name, loggy->pool); svn_error_t *err = svn_io_remove_file(full_path, loggy->pool); if (err && APR_STATUS_IS_ENOENT(err->apr_err)) { svn_error_clear(err); return SVN_NO_ERROR; } else return err;}static svn_error_t *log_do_modify_entry(struct log_runner *loggy, const char *name, const char **atts){ svn_error_t *err; apr_hash_t *ah = svn_xml_make_att_hash(atts, loggy->pool);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -