📄 update_editor.c
字号:
/* All operations are on the in-memory entries hash. */ SVN_ERR(svn_wc_adm_retrieve(&adm_access, eb->adm_access, path, pool)); SVN_ERR(svn_wc_entries_read(&entries, adm_access, TRUE, pool)); /* Mark THIS_DIR complete. */ entry = apr_hash_get(entries, SVN_WC_ENTRY_THIS_DIR, APR_HASH_KEY_STRING); if (! entry) return svn_error_createf(SVN_ERR_ENTRY_NOT_FOUND, NULL, _("No '.' entry in: '%s'"), svn_path_local_style(path, pool)); entry->incomplete = FALSE; /* Remove any deleted or missing entries. */ subpool = svn_pool_create(pool); for (hi = apr_hash_first(pool, entries); hi; hi = apr_hash_next(hi)) { const void *key; void *val; svn_pool_clear(subpool); apr_hash_this(hi, &key, NULL, &val); name = key; current_entry = val; /* Any entry still marked as deleted (and not schedule add) can now be removed -- if it wasn't undeleted by the update, then it shouldn't stay in the updated working set. Schedule add items should remain. */ if (current_entry->deleted) { if (current_entry->schedule != svn_wc_schedule_add) svn_wc__entry_remove(entries, name); else { svn_wc_entry_t tmpentry; tmpentry.deleted = FALSE; SVN_ERR(svn_wc__entry_modify(adm_access, current_entry->name, &tmpentry, SVN_WC__ENTRY_MODIFY_DELETED, FALSE, subpool)); } } /* An absent entry might have been reconfirmed as absent, and the way we can tell is by looking at its revision number: a revision number different from the target revision of the update means the update never mentioned the item, so the entry should be removed. */ else if (current_entry->absent && (current_entry->revision != *(eb->target_revision))) { svn_wc__entry_remove(entries, name); } else if (current_entry->kind == svn_node_dir) { const char *child_path = svn_path_join(path, name, subpool); if ((svn_wc__adm_missing(adm_access, child_path)) && (! current_entry->absent) && (current_entry->schedule != svn_wc_schedule_add)) { svn_wc__entry_remove(entries, name); if (eb->notify_func) { svn_wc_notify_t *notify = svn_wc_create_notify(child_path, svn_wc_notify_update_delete, subpool); notify->kind = current_entry->kind; (* eb->notify_func)(eb->notify_baton, notify, subpool); } } } } svn_pool_destroy(subpool); /* An atomic write of the whole entries file. */ SVN_ERR(svn_wc__entries_write(entries, adm_access, pool)); return SVN_NO_ERROR;}/* Decrement the bump_dir_info's reference count. If it hits zero, then this directory is "done". This means it is safe to remove the 'incomplete' flag attached to the THIS_DIR entry. In addition, when the directory is "done", we loop onto the parent's bump information to possibly mark it as done, too.*/static svn_error_t *maybe_bump_dir_info(struct edit_baton *eb, struct bump_dir_info *bdi, apr_pool_t *pool){ /* Keep moving up the tree of directories until we run out of parents, or a directory is not yet "done". */ for ( ; bdi != NULL; bdi = bdi->parent) { if (--bdi->ref_count > 0) return SVN_NO_ERROR; /* directory isn't done yet */ /* The refcount is zero, so we remove any 'dead' entries from the directory and mark it 'complete'. */ SVN_ERR(complete_directory(eb, bdi->path, bdi->parent ? FALSE : TRUE, pool)); } /* we exited the for loop because there are no more parents */ return SVN_NO_ERROR;}struct file_baton{ /* The global edit baton. */ struct edit_baton *edit_baton; /* The parent directory of this file. */ struct dir_baton *dir_baton; /* Pool specific to this file_baton. */ apr_pool_t *pool; /* Name of this file (its entry in the directory). */ const char *name; /* Path to this file, either abs or relative to the change-root. */ const char *path; /* The repository URL this file will correspond to. */ const char *new_URL; /* Set if this file is new. */ svn_boolean_t added; /* This gets set if the file underwent a text change, which guides the code that syncs up the adm dir and working copy. */ svn_boolean_t text_changed; /* This gets set if the file underwent a prop change, which guides the code that syncs up the adm dir and working copy. */ svn_boolean_t prop_changed; /* An array of svn_prop_t structures, representing all the property changes to be applied to this file. */ apr_array_header_t *propchanges; /* The last-changed-date of the file. This is actually a property that comes through as an 'entry prop', and will be used to set the working file's timestamp if it's added. */ const char *last_changed_date; /* Bump information for the directory this file lives in */ struct bump_dir_info *bump_info; /* This is initialized to all zeroes when the baton is created, then populated with the MD5 digest of the resultant fulltext after the last window is handled by the handler returned from apply_textdelta(). */ unsigned char digest[APR_MD5_DIGESTSIZE];};/* Make a new file baton in the provided POOL, with PB as the parent baton. PATH is relative to the root of the edit. */static struct file_baton *make_file_baton(struct dir_baton *pb, const char *path, svn_boolean_t adding, apr_pool_t *pool){ struct file_baton *f = apr_pcalloc(pool, sizeof(*f)); /* I rather need this information, yes. */ if (! path) abort(); /* Make the file's on-disk name. */ f->path = svn_path_join(pb->edit_baton->anchor, path, pool); f->name = svn_path_basename(path, pool); /* Figure out the new_URL for this file. */ if (pb->edit_baton->switch_url) { f->new_URL = svn_path_url_add_component(pb->new_URL, f->name, pool); } else { f->new_URL = get_entry_url(pb->edit_baton->adm_access, pb->path, f->name, pool); } f->pool = pool; f->edit_baton = pb->edit_baton; f->propchanges = apr_array_make(pool, 1, sizeof(svn_prop_t)); f->bump_info = pb->bump_info; f->added = adding; f->dir_baton = pb; /* No need to initialize f->digest, since we used pcalloc(). */ /* the directory's bump info has one more referer now */ ++f->bump_info->ref_count; return f;}/*** Helpers for the editor callbacks. ***/static svn_error_t *window_handler(svn_txdelta_window_t *window, void *baton){ struct handler_baton *hb = baton; struct file_baton *fb = hb->fb; svn_error_t *err = SVN_NO_ERROR, *err2 = SVN_NO_ERROR; /* Apply this window. We may be done at that point. */ err = hb->apply_handler(window, hb->apply_baton); if (window != NULL && err == SVN_NO_ERROR) return err; /* Either we're done (window is NULL) or we had an error. In either case, clean up the handler. */ if (hb->source) { err2 = svn_wc__close_text_base(hb->source, fb->path, 0, fb->pool); if (err2 != SVN_NO_ERROR && err == SVN_NO_ERROR) err = err2; else svn_error_clear(err2); } err2 = svn_wc__close_text_base(hb->dest, fb->path, 0, fb->pool); if (err2 != SVN_NO_ERROR) { if (err == SVN_NO_ERROR) err = err2; else svn_error_clear(err2); } svn_pool_destroy(hb->pool); if (err != SVN_NO_ERROR) { /* We failed to apply the patch; clean up the temporary file. */ const char *tmppath = svn_wc__text_base_path(fb->path, TRUE, fb->pool); apr_file_remove(tmppath, fb->pool); } else { /* Leave a note in the baton indicating that there's new text to sync up. */ fb->text_changed = 1; } return err;}/* Prepare directory for dir_baton DB for updating or checking out. * * If the path already exists, but is not a working copy for * ANCESTOR_URL and ANCESTOR_REVISION, then an error will be returned. */static svn_error_t *prep_directory(struct dir_baton *db, const char *ancestor_url, svn_revnum_t ancestor_revision, apr_pool_t *pool){ const char *repos; /* Make sure the directory exists. */ SVN_ERR(svn_wc__ensure_directory(db->path, pool)); /* Use the repository root of the anchor, but only if it actually is an ancestor of the URL of this directory. */ if (db->edit_baton->repos && svn_path_is_ancestor(db->edit_baton->repos, ancestor_url)) repos = db->edit_baton->repos; else repos = NULL; /* Make sure it's the right working copy, either by creating it so, or by checking that it is so already. */ SVN_ERR(svn_wc_ensure_adm2(db->path, NULL, ancestor_url, repos, ancestor_revision, pool)); if (! db->edit_baton->adm_access || strcmp(svn_wc_adm_access_path(db->edit_baton->adm_access), db->path)) { svn_wc_adm_access_t *adm_access; apr_pool_t *adm_access_pool = db->edit_baton->adm_access ? svn_wc_adm_access_pool(db->edit_baton->adm_access) : db->edit_baton->pool; SVN_ERR(svn_wc_adm_open3(&adm_access, db->edit_baton->adm_access, db->path, TRUE, 0, NULL, NULL, adm_access_pool)); if (!db->edit_baton->adm_access) db->edit_baton->adm_access = adm_access; } return SVN_NO_ERROR;}/* Accumulate tags in LOG_ACCUM to set ENTRY_PROPS for BASE_NAME. ENTRY_PROPS is an array of svn_prop_t* entry props. If ENTRY_PROPS contains the removal of a lock token, all entryprops related to a lock will be removed and LOCK_STATE, if non-NULL, will be set to svn_wc_notify_lock_state_unlocked. Else, LOCK_STATE, if non-NULL will be set to svn_wc_lock_state_unchanged. */static svn_error_t *accumulate_entry_props(svn_stringbuf_t *log_accum, svn_wc_notify_lock_state_t *lock_state, svn_wc_adm_access_t *adm_access, const char *base_name, apr_array_header_t *entry_props, apr_pool_t *pool){ int i; svn_wc_entry_t tmp_entry; apr_uint32_t flags = 0; if (lock_state) *lock_state = svn_wc_notify_lock_state_unchanged; for (i = 0; i < entry_props->nelts; ++i) { const svn_prop_t *prop = &APR_ARRAY_IDX(entry_props, i, svn_prop_t); const char *val; /* The removal of the lock-token entryprop means that the lock was defunct. */ if (! strcmp(prop->name, SVN_PROP_ENTRY_LOCK_TOKEN)) { SVN_ERR(svn_wc__loggy_delete_lock(&log_accum, adm_access, base_name, pool)); if (lock_state) *lock_state = svn_wc_notify_lock_state_unlocked; continue; } /* A prop value of NULL means the information was not available. We don't remove this field from the entries file; we have convention just leave it empty. So let's just skip those entry props that have no values. */ if (! prop->value) continue; val = prop->value->data; if (! strcmp(prop->name, SVN_PROP_ENTRY_LAST_AUTHOR)) { flags |= SVN_WC__ENTRY_MODIFY_CMT_AUTHOR; tmp_entry.cmt_author = val; } else if (! strcmp(prop->name, SVN_PROP_ENTRY_COMMITTED_REV)) { flags |= SVN_WC__ENTRY_MODIFY_CMT_REV; tmp_entry.cmt_rev = SVN_STR_TO_REV(val); } else if (! strcmp(prop->name, SVN_PROP_ENTRY_COMMITTED_DATE)) { flags |= SVN_WC__ENTRY_MODIFY_CMT_DATE; SVN_ERR(svn_time_from_cstring(&tmp_entry.cmt_date, val, pool)); } else if (! strcmp(prop->name, SVN_PROP_ENTRY_UUID)) { flags |= SVN_WC__ENTRY_MODIFY_UUID;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -