📄 log.c
字号:
const char *tfile; svn_wc_entry_t *entry; apr_uint32_t modify_flags; const char *valuestr; if (loggy->rerun) { /* When committing a delete the entry might get removed, in which case we don't want to reincarnate it. */ const svn_wc_entry_t *existing; const char *path = svn_path_join(svn_wc_adm_access_path(loggy->adm_access), name, loggy->pool); SVN_ERR(svn_wc_entry(&existing, path, loggy->adm_access, TRUE, loggy->pool)); if (! existing) return SVN_NO_ERROR; } /* Convert the attributes into an entry structure. */ SVN_ERR(svn_wc__atts_to_entry(&entry, &modify_flags, ah, loggy->pool)); /* Make TFILE the path of the thing being modified. */ tfile = svn_path_join(svn_wc_adm_access_path(loggy->adm_access), strcmp(name, SVN_WC_ENTRY_THIS_DIR) ? name : "", loggy->pool); /* Did the log command give us any timestamps? There are three possible scenarios here. We must check both text_time and prop_time for each of the three scenarios. */ /* TEXT_TIME: */ valuestr = apr_hash_get(ah, SVN_WC__ENTRY_ATTR_TEXT_TIME, APR_HASH_KEY_STRING); if ((modify_flags & SVN_WC__ENTRY_MODIFY_TEXT_TIME) && (! strcmp(valuestr, SVN_WC__TIMESTAMP_WC))) { apr_time_t text_time; err = svn_io_file_affected_time(&text_time, tfile, loggy->pool); if (err) return svn_error_createf (pick_error_code(loggy), err, _("Error getting 'affected time' on '%s'"), svn_path_local_style(tfile, loggy->pool)); entry->text_time = text_time; } /* PROP_TIME: */ valuestr = apr_hash_get(ah, SVN_WC__ENTRY_ATTR_PROP_TIME, APR_HASH_KEY_STRING); if ((modify_flags & SVN_WC__ENTRY_MODIFY_PROP_TIME) && (! strcmp(valuestr, SVN_WC__TIMESTAMP_WC))) { const char *pfile; apr_time_t prop_time; const svn_wc_entry_t *tfile_entry; err = svn_wc_entry(&tfile_entry, tfile, loggy->adm_access, FALSE, loggy->pool); if (err) signal_error(loggy, err); if (! tfile_entry) return SVN_NO_ERROR; err = svn_wc__prop_path(&pfile, tfile, tfile_entry->kind, FALSE, loggy->pool); if (err) signal_error(loggy, err); err = svn_io_file_affected_time(&prop_time, pfile, loggy->pool); if (err && APR_STATUS_IS_ENOENT(err->apr_err)) { svn_error_clear(err); prop_time = 0; } else if (err) return svn_error_createf (pick_error_code(loggy), NULL, _("Error getting 'affected time' on '%s'"), svn_path_local_style(pfile, loggy->pool)); entry->prop_time = prop_time; } /* Now write the new entry out */ err = svn_wc__entry_modify(loggy->adm_access, name, entry, modify_flags, FALSE, loggy->pool); if (err) return svn_error_createf(pick_error_code(loggy), err, _("Error modifying entry for '%s'"), name); loggy->entries_modified = TRUE; return SVN_NO_ERROR;}static svn_error_t *log_do_delete_lock(struct log_runner *loggy, const char *name){ svn_error_t *err; svn_wc_entry_t entry; entry.lock_token = entry.lock_comment = entry.lock_owner = NULL; entry.lock_creation_date = 0; /* Now write the new entry out */ err = svn_wc__entry_modify(loggy->adm_access, name, &entry, SVN_WC__ENTRY_MODIFY_LOCK_TOKEN | SVN_WC__ENTRY_MODIFY_LOCK_OWNER | SVN_WC__ENTRY_MODIFY_LOCK_COMMENT | SVN_WC__ENTRY_MODIFY_LOCK_CREATION_DATE, FALSE, loggy->pool); if (err) return svn_error_createf(pick_error_code(loggy), err, _("Error removing lock from entry for '%s'"), name); loggy->entries_modified = TRUE; return SVN_NO_ERROR;}/* Ben sez: this log command is (at the moment) only executed by the update editor. It attempts to forcefully remove working data. */static svn_error_t *log_do_delete_entry(struct log_runner *loggy, const char *name){ svn_wc_adm_access_t *adm_access; const svn_wc_entry_t *entry; svn_error_t *err = SVN_NO_ERROR; const char *full_path = svn_path_join(svn_wc_adm_access_path(loggy->adm_access), name, loggy->pool); /* Figure out if 'name' is a dir or a file */ SVN_ERR(svn_wc_adm_probe_retrieve(&adm_access, loggy->adm_access, full_path, loggy->pool)); SVN_ERR(svn_wc_entry(&entry, full_path, adm_access, FALSE, loggy->pool)); if (! entry) /* Hmm....this entry is already absent from the revision control system. Chances are good that this item was removed via a commit from this working copy. */ return SVN_NO_ERROR; /* Remove the object from revision control -- whether it's a single file or recursive directory removal. Attempt attempt to destroy all working files & dirs too. ### We pass NULL, NULL for cancel_func and cancel_baton below. ### If they were available, it would be nice to use them. */ if (entry->kind == svn_node_dir) { svn_wc_adm_access_t *ignored; /* If we get the right kind of error, it means the directory is already missing, so all we need to do is delete its entry in the parent directory. */ err = svn_wc_adm_retrieve(&ignored, adm_access, full_path, loggy->pool); if (err) { if (err->apr_err == SVN_ERR_WC_NOT_LOCKED) { apr_hash_t *entries; svn_error_clear(err); err = SVN_NO_ERROR; if (entry->schedule != svn_wc_schedule_add) { SVN_ERR(svn_wc_entries_read(&entries, loggy->adm_access, TRUE, loggy->pool)); svn_wc__entry_remove(entries, name); SVN_ERR(svn_wc__entries_write(entries, loggy->adm_access, loggy->pool)); } } else { return err; } } else { err = svn_wc_remove_from_revision_control(adm_access, SVN_WC_ENTRY_THIS_DIR, TRUE, /* destroy */ FALSE, /* instant_error */ NULL, NULL, loggy->pool); } } else if (entry->kind == svn_node_file) { err = svn_wc_remove_from_revision_control(loggy->adm_access, name, TRUE, /* destroy */ FALSE, /* instant_error */ NULL, NULL, loggy->pool); } if ((err) && (err->apr_err == SVN_ERR_WC_LEFT_LOCAL_MOD)) { svn_error_clear(err); return SVN_NO_ERROR; } else return err;}/* Note: assuming that svn_wc__log_commit() is what created all of the <committed...> commands, the `name' attribute will either be a file or SVN_WC_ENTRY_THIS_DIR. */static svn_error_t *log_do_committed(struct log_runner *loggy, const char *name, const char **atts){ svn_error_t *err; apr_pool_t *pool = loggy->pool; int is_this_dir = (strcmp(name, SVN_WC_ENTRY_THIS_DIR) == 0); const char *rev = svn_xml_get_attr_value(SVN_WC__LOG_ATTR_REVISION, atts); svn_boolean_t wc_root, overwrote_working = FALSE, remove_executable = FALSE; svn_boolean_t set_read_write = FALSE; const char *full_path; const char *pdir, *base_name; apr_hash_t *entries; const svn_wc_entry_t *orig_entry; svn_wc_entry_t *entry; apr_time_t text_time = 0; /* By default, don't override old stamp. */ svn_node_kind_t kind; svn_wc_adm_access_t *adm_access; /* Determine the actual full path of the affected item. */ if (! is_this_dir) full_path = svn_path_join(svn_wc_adm_access_path(loggy->adm_access), name, pool); else full_path = apr_pstrdup(pool, svn_wc_adm_access_path(loggy->adm_access)); /*** Perform sanity checking operations ***/ /* If no new post-commit revision was given us, bail with an error. */ if (! rev) return svn_error_createf(pick_error_code(loggy), NULL, _("Missing 'revision' attribute for '%s'"), name); /* Read the entry for the affected item. If we can't find the entry, or if the entry states that our item is not either "this dir" or a file kind, perhaps this isn't really the entry our log creator was expecting. */ SVN_ERR(svn_wc_adm_probe_retrieve(&adm_access, loggy->adm_access, full_path, pool)); SVN_ERR(svn_wc_entry(&orig_entry, full_path, adm_access, TRUE, pool)); /* Cannot rerun a commit of a delete since the entry gets changed too much; if it's got as far as being in state deleted=true, or if it has been removed, then the all the processing has been done. */ if (loggy->rerun && (! orig_entry || (orig_entry->schedule == svn_wc_schedule_normal && orig_entry->deleted))) return SVN_NO_ERROR; if ((! orig_entry) || ((! is_this_dir) && (orig_entry->kind != svn_node_file))) return svn_error_createf (pick_error_code(loggy), NULL, _("Log command for directory '%s' is mislocated"), name); entry = svn_wc_entry_dup(orig_entry, pool); /*** Handle the committed deletion case ***/ /* If the committed item was scheduled for deletion, it needs to now be removed from revision control. Once that is accomplished, we are finished handling this item. */ if (entry->schedule == svn_wc_schedule_delete) { svn_revnum_t new_rev = SVN_STR_TO_REV(rev); /* If we are suppose to delete "this dir", drop a 'killme' file into my own administrative dir as a signal for svn_wc__run_log() to blow away the administrative area after it is finished processing this logfile. */ if (is_this_dir) { /* Bump the revision number of this_dir anyway, so that it might be higher than its parent's revnum. If it's higher, then the process that sees KILLME and destroys the directory can also place a 'deleted' dir entry in the parent. */ svn_wc_entry_t tmpentry; tmpentry.revision = new_rev; tmpentry.kind = svn_node_dir; SVN_ERR(svn_wc__entry_modify (loggy->adm_access, NULL, &tmpentry, SVN_WC__ENTRY_MODIFY_REVISION | SVN_WC__ENTRY_MODIFY_KIND, FALSE, pool)); loggy->entries_modified = TRUE; /* Drop the 'killme' file. */ err = svn_wc__make_adm_thing(loggy->adm_access, SVN_WC__ADM_KILLME, svn_node_file, APR_OS_DEFAULT, 0, pool); if (err) { if (loggy->rerun && APR_STATUS_IS_EEXIST(err->apr_err)) svn_error_clear(err); else return err; } return SVN_NO_ERROR; } /* Else, we're deleting a file, and we can safely remove files from revision control without screwing something else up. ### We pass NULL, NULL for cancel_func and cancel_baton below. ### If they were available, it would be nice to use them. */ else { const svn_wc_entry_t *parentry; svn_wc_entry_t tmp_entry; SVN_ERR(svn_wc_remove_from_revision_control(loggy->adm_access, name, FALSE, FALSE, NULL, NULL, pool)); /* If the parent entry's working rev 'lags' behind new_rev... */ SVN_ERR(svn_wc_entry(&parentry, svn_wc_adm_access_path(loggy->adm_access), loggy->adm_access, TRUE, pool)); if (new_rev > parentry->revision) { /* ...then the parent's revision is now officially a lie; therefore, it must remember the file as being 'deleted' for a while. Create a new, uninteresting ghost entry: */ tmp_entry.kind = svn_node_file; tmp_entry.deleted = TRUE; tmp_entry.revision = new_rev; SVN_ERR(svn_wc__entry_modify (loggy->adm_access, name, &tmp_entry, SVN_WC__ENTRY_MODIFY_REVISION | SVN_WC__ENTRY_MODIFY_KIND | SVN_WC__ENTRY_MODIFY_DELETED, FALSE, pool)); loggy->entries_modified = TRUE; } return SVN_NO_ERROR; } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -