⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 update_editor.c

📁 subversion-1.4.3-1.tar.gz 配置svn的源码
💻 C
📖 第 1 页 / 共 5 页
字号:
          tmp_entry.uuid = val;        }    }  if (flags)    SVN_ERR(svn_wc__loggy_entry_modify(&log_accum, adm_access, base_name,                                       &tmp_entry, flags, pool));  return SVN_NO_ERROR;}/* Accumulate tags in LOG_ACCUM to set WCPROPS for BASE_NAME.  WCPROPS is   an array of svn_prop_t* wc props. */static svn_error_t *accumulate_wcprops(svn_stringbuf_t *log_accum,                   svn_wc_adm_access_t *adm_access,                   const char *base_name,                   apr_array_header_t *wcprops,                   apr_pool_t *pool){  int i;  /* ### The log file will rewrite the props file for each property :( It     ### would be better if all the changes could be combined into one     ### write. */  for (i = 0; i < wcprops->nelts; ++i)    {      const svn_prop_t *prop = &APR_ARRAY_IDX(wcprops, i, svn_prop_t);      SVN_ERR(svn_wc__loggy_modify_wcprop              (&log_accum, adm_access,               base_name,               prop->name, prop->value ? prop->value->data : NULL, pool));    }  return SVN_NO_ERROR;}      /*** The callbacks we'll plug into an svn_delta_editor_t structure. ***/static svn_error_t *set_target_revision(void *edit_baton,                     svn_revnum_t target_revision,                    apr_pool_t *pool){  struct edit_baton *eb = edit_baton;  /* Stashing a target_revision in the baton */  *(eb->target_revision) = target_revision;  return SVN_NO_ERROR;}static svn_error_t *open_root(void *edit_baton,          svn_revnum_t base_revision, /* This is ignored in co */          apr_pool_t *pool,          void **dir_baton){  struct edit_baton *eb = edit_baton;  struct dir_baton *d;  /* Note that something interesting is actually happening in this     edit run. */  eb->root_opened = TRUE;  *dir_baton = d = make_dir_baton(NULL, eb, NULL, FALSE, pool);  if (! *eb->target)    {      /* For an update with a NULL target, this is equivalent to open_dir(): */      svn_wc_adm_access_t *adm_access;      svn_wc_entry_t tmp_entry;      apr_uint32_t flags = SVN_WC__ENTRY_MODIFY_REVISION |        SVN_WC__ENTRY_MODIFY_URL | SVN_WC__ENTRY_MODIFY_INCOMPLETE;                                           /* Mark directory as being at target_revision, but incomplete. */        tmp_entry.revision = *(eb->target_revision);      tmp_entry.url = d->new_URL;      /* See open_directory() for why this check is necessary. */      if (eb->repos && svn_path_is_ancestor(eb->repos, d->new_URL))        {          tmp_entry.repos = eb->repos;          flags |= SVN_WC__ENTRY_MODIFY_REPOS;        }      tmp_entry.incomplete = TRUE;      SVN_ERR(svn_wc_adm_retrieve(&adm_access, eb->adm_access,                                  d->path, pool));      SVN_ERR(svn_wc__entry_modify(adm_access, NULL /* THIS_DIR */,                                   &tmp_entry, flags,                                   TRUE /* immediate write */,                                   pool));    }  return SVN_NO_ERROR;}/* Helper for delete_entry().   Search an error chain (ERR) for evidence that a local mod was left.   If so, cleanup LOGFILE and return an appropriate error.  Otherwise,   just return the original error chain.*/static svn_error_t *leftmod_error_chain(svn_error_t *err,                    const char *logfile,                    const char *path,                    apr_pool_t *pool){  svn_error_t *tmp_err;  if (! err)    return SVN_NO_ERROR;  /* Advance TMP_ERR to the part of the error chain that reveals that     a local mod was left, or to the NULL end of the chain. */  for (tmp_err = err; tmp_err; tmp_err = tmp_err->child)    if (tmp_err->apr_err == SVN_ERR_WC_LEFT_LOCAL_MOD)      break;  /* If we found a "left a local mod" error, wrap and return it.     Otherwise, we just return our top-most error. */  if (tmp_err)    {      /* Remove the LOGFILE (and eat up errors from this process). */      svn_error_clear(svn_io_remove_file(logfile, pool));      return svn_error_createf        (SVN_ERR_WC_OBSTRUCTED_UPDATE, tmp_err,         _("Won't delete locally modified directory '%s'"),         svn_path_local_style(path, pool));    }  return err;}static svn_error_t *do_entry_deletion(struct edit_baton *eb,                  const char *parent_path,                  const char *path,                  int *log_number,                  apr_pool_t *pool){  apr_file_t *log_fp = NULL;  const char *base_name;  svn_wc_adm_access_t *adm_access;  svn_node_kind_t kind;  const char *logfile_path, *logfile_name;  const char *full_path = svn_path_join(eb->anchor, path, pool);  svn_stringbuf_t *log_item = svn_stringbuf_create("", pool);  SVN_ERR(svn_io_check_path(full_path, &kind, pool));  SVN_ERR(svn_wc_adm_retrieve(&adm_access, eb->adm_access,                              parent_path, pool));  logfile_name = svn_wc__logfile_path(*log_number, pool);    logfile_path = svn_wc__adm_path(parent_path, FALSE, pool,                                  logfile_name, NULL);  SVN_ERR(svn_wc__open_adm_file(&log_fp,                                parent_path,                                logfile_name,                                (APR_WRITE | APR_CREATE), /* not excl */                                pool));  /* Here's the deal: in the new editor interface, PATH is a full path     below the editor's anchor, and parent_path is the parent directory.     That's all fine and well, but our log-system requires that all     log commands talk *only* about paths relative (and below)     parent_path, i.e. where the log is being executed.  */  base_name = svn_path_basename(path, pool);  SVN_ERR(svn_wc__loggy_delete_entry(&log_item, adm_access,                                     base_name, pool));  /* If the thing being deleted is the *target* of this update, then     we need to recreate a 'deleted' entry, so that parent can give     accurate reports about itself in the future. */  if (strcmp(path, eb->target) == 0)    {      svn_wc_entry_t tmp_entry;      tmp_entry.revision = *(eb->target_revision);      tmp_entry.kind = (kind == svn_node_file) ? svn_node_file : svn_node_dir;      tmp_entry.deleted = TRUE;      SVN_ERR(svn_wc__loggy_entry_modify(&log_item, adm_access,                                         path, &tmp_entry,                                         /*### path should have been base_name?! */                                         SVN_WC__ENTRY_MODIFY_REVISION                                         | SVN_WC__ENTRY_MODIFY_KIND                                         | SVN_WC__ENTRY_MODIFY_DELETED,                                         pool));      eb->target_deleted = TRUE;    }  SVN_ERR_W(svn_io_file_write_full(log_fp, log_item->data,                                    log_item->len, NULL, pool),            apr_psprintf(pool,                          _("Error writing log file for '%s'"),                         svn_path_local_style(parent_path, pool)));  SVN_ERR(svn_wc__close_adm_file(log_fp,                                 parent_path,                                 logfile_name,                                 TRUE, /* sync */                                 pool));      if (eb->switch_url)    {      /* The SVN_WC__LOG_DELETE_ENTRY log item will cause       * svn_wc_remove_from_revision_control() to be run.  But that       * function checks whether the deletion target's URL is child of       * its parent directory's URL, and if it's not, then the entry       * in parent won't be deleted (because presumably the child       * represents a disjoint working copy, i.e., it is a wc_root).       *       * However, during a switch this works against us, because by       * the time we get here, the parent's URL has already been       * changed.  So we manually remove the child from revision       * control after the delete-entry item has been written in the       * parent's log, but before it is run, so the only work left for       * the log item is to remove the entry in the parent directory.       */      if (kind == svn_node_dir)        {          svn_wc_adm_access_t *child_access;          SVN_ERR(svn_wc_adm_retrieve                  (&child_access, eb->adm_access,                   full_path, pool));                    SVN_ERR(leftmod_error_chain                   (svn_wc_remove_from_revision_control                    (child_access,                    SVN_WC_ENTRY_THIS_DIR,                    TRUE, /* destroy */                    TRUE, /* instant error */                    eb->cancel_func,                    eb->cancel_baton,                    pool),                   logfile_path, parent_path, pool));        }    }  SVN_ERR(leftmod_error_chain(svn_wc__run_log(adm_access, NULL, pool),                              logfile_path, parent_path, pool));  *log_number = 0;  /* The passed-in `path' is relative to the anchor of the edit, so if   * the operation was invoked on something other than ".", then   * `path' will be wrong for purposes of notification.  However, we   * can always count on the parent_path being the parent of base_name,   * so we just join them together to get a good notification path.   */  if (eb->notify_func)    (*eb->notify_func)      (eb->notify_baton,       svn_wc_create_notify(svn_path_join(parent_path, base_name, pool),                            svn_wc_notify_update_delete, pool), pool);  return SVN_NO_ERROR;}static svn_error_t *delete_entry(const char *path,              svn_revnum_t revision,              void *parent_baton,             apr_pool_t *pool){  struct dir_baton *pb = parent_baton;  return do_entry_deletion(pb->edit_baton, pb->path, path, &pb->log_number,                           pool);}static svn_error_t *add_directory(const char *path,              void *parent_baton,              const char *copyfrom_path,              svn_revnum_t copyfrom_revision,              apr_pool_t *pool,              void **child_baton){  struct dir_baton *pb = parent_baton;  struct edit_baton *eb = pb->edit_baton;  struct dir_baton *db = make_dir_baton(path, eb, pb, TRUE, pool);  svn_node_kind_t kind;  /* Semantic check.  Either both "copyfrom" args are valid, or they're     NULL and SVN_INVALID_REVNUM.  A mixture is illegal semantics. */  if ((copyfrom_path && (! SVN_IS_VALID_REVNUM(copyfrom_revision)))      || ((! copyfrom_path) && (SVN_IS_VALID_REVNUM(copyfrom_revision))))    abort();  /* There should be nothing with this name. */  SVN_ERR(svn_io_check_path(db->path, &kind, db->pool));  if (kind != svn_node_none)    return svn_error_createf      (SVN_ERR_WC_OBSTRUCTED_UPDATE, NULL,       _("Failed to add directory '%s': "         "object of the same name already exists"),       svn_path_local_style(db->path, pool));  /* It may not be named the same as the administrative directory. */  if (svn_wc_is_adm_dir(svn_path_basename(path, pool), pool))    return svn_error_createf      (SVN_ERR_WC_OBSTRUCTED_UPDATE, NULL,       _("Failed to add directory '%s': object of the same name as the "         "administrative directory"),       svn_path_local_style(db->path, pool));  /* Either we got real copyfrom args... */  if (copyfrom_path || SVN_IS_VALID_REVNUM(copyfrom_revision))    {      /* ### todo: for now, this editor doesn't know how to deal with         copyfrom args.  Someday it will interpet them as an update         optimization, and actually copy one part of the wc to another.         Then it will recursively "normalize" all the ancestry in the         copied tree.  Someday! */            return svn_error_createf        (SVN_ERR_UNSUPPORTED_FEATURE, NULL,         _("Failed to add directory '%s': "           "copyfrom arguments not yet supported"),         svn_path_local_style(db->path, pool));    }  else  /* ...or we got invalid copyfrom args. */    {      svn_wc_adm_access_t *adm_access;      const svn_wc_entry_t *dir_entry;      apr_hash_t *entries;      svn_wc_entry_t tmp_entry;      /* Extra check:  a directory by this name may not exist, but there         may still be one scheduled for addition.  That's a genuine         tree-conflict.  */      SVN_ERR(svn_wc_adm_retrieve(&adm_access, eb->adm_access,                                  pb->path, db->pool));      SVN_ERR(svn_wc_entries_read(&entries, adm_access, FALSE, db->pool));      dir_entry = apr_hash_get(entries, db->name, APR_HASH_KEY_STRING);      if (dir_entry && dir_entry->schedule == svn_wc_schedule_add)        return svn_error_createf          (SVN_ERR_WC_OBSTRUCTED_UPDATE, NULL,           _("Failed to add directory '%s': object of the same name "             "is already scheduled for addition"),           svn_path_local_style(path, pool));      /* Immediately create an entry for the new directory in the parent.         Note that the parent must already be either added or opened, and         thus it's in an 'incomplete' state just like the new dir.  */            tmp_entry.kind = svn_node_dir;      /* Note that there may already exist a 'ghost' entry in the         parent with the same name, in a 'deleted' or 'absent' state.         If so, it's fine to overwrite it... but we need to make sure         we get rid of the state flag when doing so: */      tmp_entry.deleted = FALSE;      tmp_entry.absent = FALSE;      SVN_ERR(svn_wc__entry_modify(adm_access, db->name, &tmp_entry,                                   (SVN_WC__ENTRY_MODIFY_KIND    |                                    SVN_WC__ENTRY_MODIFY_DELETED |                                    SVN_WC__ENTRY_MODIFY_ABSENT),                                   TRUE /* immediate write */, pool));    }  SVN_ERR(prep_directory(db,                         db->new_URL,                         *(eb->target_revision),                         db->pool));  *child_baton = db;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -