📄 log.c
字号:
/*** Mark the committed item committed-to-date ***/ /* If "this dir" has been replaced (delete + add), all its immmediate children *must* be either scheduled for deletion (they were children of "this dir" during the "delete" phase of its replacement), added (they are new children of the replaced dir), or replaced (they are new children of the replace dir that have the same names as children that were present during the "delete" phase of the replacement). Children which are added or replaced will have been reported as individual commit targets, and thus will be re-visited by log_do_committed(). Children which were marked for deletion, however, need to be outright removed from revision control. */ if ((entry->schedule == svn_wc_schedule_replace) && is_this_dir) { apr_hash_index_t *hi; /* Loop over all children entries, look for items scheduled for deletion. */ SVN_ERR(svn_wc_entries_read(&entries, loggy->adm_access, TRUE, pool)); for (hi = apr_hash_first(pool, entries); hi; hi = apr_hash_next(hi)) { const void *key; apr_ssize_t klen; void *val; const svn_wc_entry_t *cur_entry; svn_wc_adm_access_t *entry_access; /* Get the next entry */ apr_hash_this(hi, &key, &klen, &val); cur_entry = (svn_wc_entry_t *) val; /* Skip each entry that isn't scheduled for deletion. */ if (cur_entry->schedule != svn_wc_schedule_delete) continue; /* Determine what arguments to hand to our removal function, and let BASE_NAME double as an "ok" flag to run that function. */ base_name = NULL; if (cur_entry->kind == svn_node_file) { pdir = svn_wc_adm_access_path(loggy->adm_access); base_name = apr_pstrdup(pool, key); entry_access = loggy->adm_access; } else if (cur_entry->kind == svn_node_dir) { pdir = svn_path_join(svn_wc_adm_access_path(loggy->adm_access), key, pool); base_name = SVN_WC_ENTRY_THIS_DIR; SVN_ERR(svn_wc_adm_retrieve(&entry_access, loggy->adm_access, pdir, pool)); } /* ### We pass NULL, NULL for cancel_func and cancel_baton below. ### If they were available, it would be nice to use them. */ if (base_name) SVN_ERR(svn_wc_remove_from_revision_control (entry_access, base_name, FALSE, FALSE, NULL, NULL, pool)); } } /* For file commit items, we need to "install" the user's working file as the new `text-base' in the administrative area. A copy of this file should have been dropped into our `tmp/text-base' directory during the commit process. Part of this process involves setting the textual timestamp for this entry. We'd like to just use the timestamp of the working file, but it is possible that at some point during the commit, the real working file might have changed again. If that has happened, we'll use the timestamp of the copy of this file in `tmp/text-base'. */ if (! is_this_dir) { const char *wf = full_path, *tmpf; /* Make sure our working file copy is present in the temp area. */ tmpf = svn_wc__text_base_path(wf, 1, pool); if ((err = svn_io_check_path(tmpf, &kind, pool))) return svn_error_createf(pick_error_code(loggy), err, _("Error checking existence of '%s'"), name); if (kind == svn_node_file) { svn_boolean_t modified = FALSE; apr_time_t wf_time, tmpf_time; /* Get the timestamp from working and temporary base file. */ if ((err = svn_io_file_affected_time(&wf_time, wf, pool))) return svn_error_createf (pick_error_code(loggy), err, _("Error getting 'affected time' for '%s'"), svn_path_local_style(wf, pool)); if ((err = svn_io_file_affected_time(&tmpf_time, tmpf, pool))) return svn_error_createf (pick_error_code(loggy), err, _("Error getting 'affected time' for '%s'"), svn_path_local_style(tmpf, pool)); /* Verify that the working file is the same as the tmpf file. */ if (wf_time != tmpf_time) { if ((err = svn_wc__versioned_file_modcheck(&modified, wf, loggy->adm_access, tmpf, TRUE, pool))) return svn_error_createf(pick_error_code(loggy), err, _("Error comparing '%s' and '%s'"), svn_path_local_style(wf, pool), svn_path_local_style(tmpf, pool)); } /* If they are the same, use the working file's timestamp, else use the tmpf file's timestamp. */ text_time = modified ? tmpf_time : wf_time; } } /* Now check for property commits. If a property commit occurred, a copy of the "working" property file should have been dumped in the admistrative `tmp' area. We'll let that tmpfile's existence be a signal that we need to do post-commit property processing. Also, we have to again decide which timestamp to use (see the text-time case above). */ { const char *tmpf, *basef; /* Get property file pathnames (not from the `tmp' area) depending on whether we're examining a file or THIS_DIR */ /* ### Logic check: if is_this_dir, then full_path is the same as loggy->adm_access->path, I think. In which case we don't need the inline conditionals below... */ SVN_ERR(svn_wc__prop_base_path (&basef, is_this_dir ? svn_wc_adm_access_path(loggy->adm_access) : full_path, entry->kind, FALSE, pool)); /* If this file was replaced in the commit, then we definitely need to begin by removing any old residual prop-base file. */ if (entry->schedule == svn_wc_schedule_replace) { svn_node_kind_t kinder; SVN_ERR(svn_io_check_path(basef, &kinder, pool)); if (kinder == svn_node_file) SVN_ERR(svn_io_remove_file(basef, pool)); } SVN_ERR(svn_wc__prop_path (&tmpf, is_this_dir ? svn_wc_adm_access_path(loggy->adm_access) : full_path, entry->kind, TRUE, pool)); if ((err = svn_io_check_path(tmpf, &kind, pool))) return svn_error_createf(pick_error_code(loggy), err, _("Error checking existence of '%s'"), svn_path_local_style(tmpf, pool)); if (kind == svn_node_file) { /* Examine propchanges here before installing the new propbase. If the executable prop was -deleted-, then tell install_committed_file() so. The same applies to the needs-lock property. */ if (! is_this_dir) { int i; apr_array_header_t *propchanges; SVN_ERR(svn_wc_get_prop_diffs(&propchanges, NULL, full_path, loggy->adm_access, pool)); for (i = 0; i < propchanges->nelts; i++) { svn_prop_t *propchange = &APR_ARRAY_IDX(propchanges, i, svn_prop_t); if ((! strcmp(propchange->name, SVN_PROP_EXECUTABLE)) && (propchange->value == NULL)) { remove_executable = TRUE; break; } } for (i = 0; i < propchanges->nelts; i++) { svn_prop_t *propchange = &APR_ARRAY_IDX(propchanges, i, svn_prop_t); if ((! strcmp(propchange->name, SVN_PROP_NEEDS_LOCK)) && (propchange->value == NULL)) { set_read_write = TRUE; break; } } } /* Make the tmp prop file the new pristine one. */ SVN_ERR(svn_io_file_rename(tmpf, basef, pool)); SVN_ERR(svn_io_set_file_read_only(basef, FALSE, pool)); } } /* Timestamps have been decided on, and prop-base has been installed if necessary. Now we install the new text-base (if present), and possibly re-translate the working file. */ if (! is_this_dir) { /* Install the new file, which may involve expanding keywords. */ if ((err = install_committed_file (&overwrote_working, loggy->adm_access, name, remove_executable, set_read_write, pool))) return svn_error_createf (pick_error_code(loggy), err, _("Error replacing text-base of '%s'"), name); /* If the working file was overwritten (due to re-translation) or touched (due to +x / -x), then use *that* textual timestamp instead. */ if (overwrote_working) if ((err = svn_io_file_affected_time(&text_time, full_path, pool))) return svn_error_createf(pick_error_code(loggy), err, _("Error getting 'affected time' of '%s'"), svn_path_local_style(full_path, pool)); } /* Files have been moved, and timestamps have been found. It is now time for The Big Entry Modification. */ entry->revision = SVN_STR_TO_REV(rev); entry->kind = is_this_dir ? svn_node_dir : svn_node_file; entry->schedule = svn_wc_schedule_normal; entry->copied = FALSE; entry->deleted = FALSE; entry->text_time = text_time; entry->conflict_old = NULL; entry->conflict_new = NULL; entry->conflict_wrk = NULL; entry->prejfile = NULL; entry->copyfrom_url = NULL; entry->copyfrom_rev = SVN_INVALID_REVNUM; entry->has_prop_mods = FALSE; if ((err = svn_wc__entry_modify(loggy->adm_access, name, entry, (SVN_WC__ENTRY_MODIFY_REVISION | SVN_WC__ENTRY_MODIFY_SCHEDULE | SVN_WC__ENTRY_MODIFY_COPIED | SVN_WC__ENTRY_MODIFY_DELETED | SVN_WC__ENTRY_MODIFY_COPYFROM_URL | SVN_WC__ENTRY_MODIFY_COPYFROM_REV | SVN_WC__ENTRY_MODIFY_CONFLICT_OLD | SVN_WC__ENTRY_MODIFY_CONFLICT_NEW | SVN_WC__ENTRY_MODIFY_CONFLICT_WRK | SVN_WC__ENTRY_MODIFY_PREJFILE | (text_time ? SVN_WC__ENTRY_MODIFY_TEXT_TIME : 0) | SVN_WC__ENTRY_MODIFY_HAS_PROP_MODS | SVN_WC__ENTRY_MODIFY_FORCE), FALSE, pool))) return svn_error_createf (pick_error_code(loggy), err, _("Error modifying entry of '%s'"), name); loggy->entries_modified = TRUE; /* Remove the working props file if it exists. This is done here, after resetting the has_prop_mods flag, since the text-base install stuff above will need this file if props_mod was set. */ { const char *wf; SVN_ERR(svn_wc__prop_path (&wf, is_this_dir ? svn_wc_adm_access_path(loggy->adm_access) : full_path, entry->kind, FALSE, pool)); if ((err = svn_io_remove_file(wf, pool)) && APR_STATUS_IS_ENOENT(err->apr_err)) svn_error_clear(err); else if (err) return err; } /* If we aren't looking at "this dir" (meaning we are looking at a file), we are finished. From here on out, it's all about a directory's entry in its parent. */ if (! is_this_dir) return SVN_NO_ERROR; /* For directories, we also have to reset the state in the parent's entry for this directory, unless the current directory is a `WC root' (meaning, our parent directory on disk is not our parent in Version Control Land), in which case we're all finished here. */ SVN_ERR(svn_wc_is_wc_root(&wc_root, svn_wc_adm_access_path(loggy->adm_access), loggy->adm_access, pool)); if (wc_root) return SVN_NO_ERROR; /* Make sure our entry exists in the parent. */ { svn_wc_adm_access_t *paccess; svn_boolean_t unassociated = FALSE; svn_path_split(svn_wc_adm_access_path(loggy->adm_access), &pdir, &base_name, pool); err = svn_wc_adm_retrieve(&paccess, loggy->adm_access, pdir, pool); if (err && (err->apr_err == SVN_ERR_WC_NOT_LOCKED)) { svn_error_clear(err); SVN_ERR(svn_wc_adm_open3(&paccess, NULL, pdir, TRUE, 0, NULL, NULL, pool)); unassociated = TRUE; } else if (err) return err; SVN_ERR(svn_wc_entries_read(&entries, paccess, FALSE, pool)); if (apr_hash_get(entries, base_name, APR_HASH_KEY_STRING)) { if ((err = svn_wc__entry_modify(paccess, base_name, entry, (SVN_WC__ENTRY_MODIFY_SCHEDULE | SVN_WC__ENTRY_MODIFY_COPIED | SVN_WC__ENTRY_MODIFY_DELETED | SVN_WC__ENTRY_MODIFY_FORCE), TRUE, pool))) return svn_error_createf(pick_error_code(loggy), err, _("Error modifying entry of '%s'"), name); } if (unassociated) SVN_ERR(svn_wc_adm_close(paccess)); } return SVN_NO_ERROR;}/* See documentation for SVN_WC__LOG_MODIFY_WCPROP. */static svn_error_t *log_do_modify_wcprop(struct log_runner *loggy, const char *name, const char **atts){ svn_string_t value; const char *propname, *propval, *path; if (strcmp(name, SVN_WC_ENTRY_THIS_DIR) == 0) path = svn_wc_adm_access_path(loggy->adm_access); else path = svn_path_join(svn_wc_adm_access_path(loggy->adm_access), name, loggy->pool); propname = svn_xml_get_attr_value(SVN_WC__LOG_ATTR_PROPNAME, atts); propval = svn_xml_get_attr_value(SVN_WC__LOG_ATTR_PROPVAL, atts); if (propval)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -