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

📄 update_editor.c

📁 linux subdivision ying gai ke yi le ba
💻 C
📖 第 1 页 / 共 5 页
字号:
                                     TRUE /* immediate write */, pool));
    }

  SVN_ERR (prep_directory (db,
                           db->new_URL,
                           *(eb->target_revision),
                           db->pool));

  *child_baton = db;

  if (eb->notify_func)
    (*eb->notify_func) (eb->notify_baton,
                        db->path,
                        svn_wc_notify_update_add,
                        svn_node_dir,
                        NULL,
                        svn_wc_notify_state_unknown,
                        svn_wc_notify_state_unknown,
                        SVN_INVALID_REVNUM);

  return SVN_NO_ERROR;
}


static svn_error_t *
open_directory (const char *path,
                void *parent_baton,
                svn_revnum_t base_revision,
                apr_pool_t *pool,
                void **child_baton)
{
  struct dir_baton *pb = parent_baton;
  struct edit_baton *eb = pb->edit_baton;
  svn_wc_entry_t tmp_entry;
  svn_wc_adm_access_t *adm_access;

  /* kff todo: check that the dir exists locally, find it somewhere if
     its not there?  Yes, all this and more...  And ancestor_url and
     ancestor_revision need to get used. */

  struct dir_baton *db = make_dir_baton (path, eb, pb, FALSE, pool);
  *child_baton = db;

  /* Mark directory as being at target_revision and URL, but incomplete. */
  tmp_entry.revision = *(eb->target_revision);
  tmp_entry.url = db->new_URL;
  tmp_entry.incomplete = TRUE;

  SVN_ERR (svn_wc_adm_retrieve (&adm_access, eb->adm_access,
                                db->path, pool));  
  SVN_ERR (svn_wc__entry_modify (adm_access, NULL /* THIS_DIR */,
                                 &tmp_entry,
                                 SVN_WC__ENTRY_MODIFY_REVISION |
                                 SVN_WC__ENTRY_MODIFY_URL |
                                 SVN_WC__ENTRY_MODIFY_INCOMPLETE,
                                 TRUE /* immediate write */,
                                 pool));

  return SVN_NO_ERROR;
}


static svn_error_t *
change_dir_prop (void *dir_baton,
                 const char *name,
                 const svn_string_t *value,
                 apr_pool_t *pool)
{
  svn_prop_t *propchange;
  struct dir_baton *db = dir_baton;

  propchange = apr_array_push (db->propchanges);
  propchange->name = apr_pstrdup (db->pool, name);
  propchange->value = value ? svn_string_dup (value, db->pool) : NULL;

  return SVN_NO_ERROR;
}



/* If any of the svn_prop_t objects in PROPCHANGES represents a change
   to the SVN_PROP_EXTERNALS property, return that change, else return
   null.  If PROPCHANGES contains more than one such change, return
   the first. */
static const svn_prop_t *
externals_prop_changed (apr_array_header_t *propchanges)
{
  int i;

  for (i = 0; i < propchanges->nelts; i++)
    {
      const svn_prop_t *p = &(APR_ARRAY_IDX(propchanges, i, svn_prop_t));
      if (strcmp (p->name, SVN_PROP_EXTERNALS) == 0)
        return p;
    }

  return NULL;
}

static svn_error_t *
close_directory (void *dir_baton,
                 apr_pool_t *pool)
{
  struct dir_baton *db = dir_baton;
  svn_wc_notify_state_t prop_state = svn_wc_notify_state_unknown;
  apr_array_header_t *entry_props, *wc_props, *regular_props;
  svn_wc_adm_access_t *adm_access;
      
  SVN_ERR (svn_categorize_props (db->propchanges, &entry_props, &wc_props,
                                 &regular_props, pool));

  SVN_ERR (svn_wc_adm_retrieve (&adm_access, db->edit_baton->adm_access,
                                db->path, db->pool));
      
  /* If this directory has property changes stored up, now is the time
     to deal with them. */
  if (regular_props->nelts || entry_props->nelts || wc_props->nelts)
    {
      apr_file_t *log_fp = NULL;
      const char *logfile_name;

      /* to hold log messages: */
      svn_stringbuf_t *entry_accum = svn_stringbuf_create ("", db->pool);

      logfile_name = svn_wc__logfile_path (db->log_number, pool);
      
      /* Open log file */
      SVN_ERR (svn_wc__open_adm_file (&log_fp,
                                      db->path,
                                      logfile_name,
                                      (APR_WRITE | APR_CREATE), /* not excl */
                                      db->pool));

      if (regular_props->nelts)
        {
          svn_boolean_t prop_modified;

          /* If recording traversal info, then see if the
             SVN_PROP_EXTERNALS property on this directory changed,
             and record before and after for the change. */
          if (db->edit_baton->traversal_info)
            {
              svn_wc_traversal_info_t *ti = db->edit_baton->traversal_info;
              const svn_prop_t *change = externals_prop_changed (regular_props);

              if (change)
                {
                  const svn_string_t *new_val_s = change->value;
                  const svn_string_t *old_val_s;

                  SVN_ERR (svn_wc_prop_get
                           (&old_val_s, SVN_PROP_EXTERNALS,
                            db->path, adm_access, db->pool));

                  if ((new_val_s == NULL) && (old_val_s == NULL))
                    ; /* No value before, no value after... so do nothing. */
                  else if (new_val_s && old_val_s
                           && (svn_string_compare (old_val_s, new_val_s)))
                    ; /* Value did not change... so do nothing. */
                  else  /* something changed, record the change */
                    {
                      /* We can't assume that ti came pre-loaded with the
                         old values of the svn:externals property.  Yes,
                         most callers will have already initialized ti by
                         sending it through svn_wc_crawl_revisions, but we
                         shouldn't count on that here -- so we set both the
                         old and new values again. */

                      if (old_val_s)
                        apr_hash_set (ti->externals_old,
                                      apr_pstrdup (ti->pool, db->path),
                                      APR_HASH_KEY_STRING,
                                      apr_pstrmemdup (ti->pool, old_val_s->data,
                                                      old_val_s->len));

                      if (new_val_s)
                        apr_hash_set (ti->externals_new,
                                      apr_pstrdup (ti->pool, db->path),
                                      APR_HASH_KEY_STRING,
                                      apr_pstrmemdup (ti->pool, new_val_s->data,
                                                      new_val_s->len));
                    }
                }
            }

          /* Merge pending properties into temporary files (ignoring
             conflicts). */
          SVN_ERR_W (svn_wc__merge_prop_diffs (&prop_state,
                                               adm_access, NULL,
                                               regular_props, TRUE, FALSE,
                                               db->pool, &entry_accum),
                     _("Couldn't do property merge"));

          /* Are the directory's props locally modified? */
          SVN_ERR (svn_wc_props_modified_p (&prop_modified,
                                            db->path, adm_access,
                                            db->pool));

          /* Log entry which sets a new property timestamp, but *only* if
             there are no local changes to the props. */
          if (! prop_modified)
            svn_xml_make_open_tag (&entry_accum,
                                   db->pool,
                                   svn_xml_self_closing,
                                   SVN_WC__LOG_MODIFY_ENTRY,
                                   SVN_WC__LOG_ATTR_NAME,
                                   SVN_WC_ENTRY_THIS_DIR,
                                   SVN_WC__ENTRY_ATTR_PROP_TIME,
                                   /* use wfile time */
                                   SVN_WC_TIMESTAMP_WC,
                                   NULL);
        }

      accumulate_entry_props (entry_accum, SVN_WC_ENTRY_THIS_DIR, entry_props,
                              pool);

      accumulate_wcprops (entry_accum, SVN_WC_ENTRY_THIS_DIR, wc_props, pool);

      /* Write our accumulation of log entries into a log file */
      SVN_ERR_W (svn_io_file_write_full (log_fp, entry_accum->data,
                                         entry_accum->len, NULL, pool),
                 apr_psprintf (pool,
                               _("Error writing log file for '%s'"),
                               db->path));

      /* The log is ready to run, close it. */
      SVN_ERR (svn_wc__close_adm_file (log_fp,
                                       db->path,
                                       logfile_name,
                                       TRUE, /* sync */
                                       db->pool));

    }

  /* Run the log. */
  SVN_ERR (svn_wc__run_log (adm_access, db->edit_baton->diff3_cmd, db->pool));
  db->log_number = 0;
  
  /* We're done with this directory, so remove one reference from the
     bump information. This may trigger a number of actions. See
     maybe_bump_dir_info() for more information.  */
  SVN_ERR (maybe_bump_dir_info (db->edit_baton, db->bump_info, db->pool));

  /* Notify of any prop changes on this directory -- but do nothing
     if it's an added directory, because notification has already
     happened in that case. */
  if ((! db->added) && (db->edit_baton->notify_func))
    (*db->edit_baton->notify_func) (db->edit_baton->notify_baton,
                                    db->path,
                                    svn_wc_notify_update_update,
                                    svn_node_dir,
                                    NULL,
                                    svn_wc_notify_state_unknown,
                                    prop_state,
                                    SVN_INVALID_REVNUM);

  return SVN_NO_ERROR;
}


/* Common code for 'absent_file' and 'absent_directory'. */
static svn_error_t *
absent_file_or_dir (const char *path,
                    svn_node_kind_t kind,
                    void *parent_baton,
                    apr_pool_t *pool)
{
  const char *name = svn_path_basename (path, pool);
  struct dir_baton *pb = parent_baton;
  struct edit_baton *eb = pb->edit_baton;
  svn_wc_adm_access_t *adm_access;
  apr_hash_t *entries;
  const svn_wc_entry_t *ent;
  svn_wc_entry_t tmp_entry;

  /* Extra check: an item 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, pool));
  SVN_ERR (svn_wc_entries_read (&entries, adm_access, FALSE, pool));
  ent = apr_hash_get (entries, name, APR_HASH_KEY_STRING);
  if (ent && (ent->schedule == svn_wc_schedule_add))
    return svn_error_createf
      (SVN_ERR_WC_OBSTRUCTED_UPDATE, NULL,
       _("Failed to mark '%s' absent: item of the same name is already "
         "scheduled for addition"), path);
  
  /* Immediately create an entry for the new item 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 item.  */
  tmp_entry.kind = kind;

  /* Note that there may already exist a 'ghost' entry in the parent
     with the same name, in a 'deleted' state.  If so, it's fine to
     overwrite it... but we need to make sure we get rid of the
     'deleted' flag when doing so: */
  tmp_entry.deleted = FALSE;

  /* Post-update processing knows to leave this entry if its revision
     is equal to the target revision of the overall update. */
  tmp_entry.revision = *(eb->target_revision);

  /* And, of course, marking as absent is the whole point. */
  tmp_entry.absent = TRUE;

  SVN_ERR (svn_wc__entry_modify (adm_access, name, &tmp_entry,
                                 (SVN_WC__ENTRY_MODIFY_KIND    |
                                  SVN_WC__ENTRY_MODIFY_REVISION |
                                  SVN_WC__ENTRY_MODIFY_DELETED |
                                  SVN_WC__ENTRY_MODIFY_ABSENT),
                                 TRUE /* immediate write */, pool));

  return SVN_NO_ERROR;
}


static svn_error_t *
absent_file (const char *path,
             void *parent_baton,
             apr_pool_t *pool)
{
  return absent_file_or_dir (path, svn_node_file, parent_baton, pool);
}


static svn_error_t *
absent_directory (const char *path,
                  void *parent_baton,
                  apr_pool_t *pool)
{
  return absent_file_or_dir (path, svn_node_dir, parent_baton, pool);
}


/* Common code for add_file() and open_file(). */
static svn_error_t *
add_or_open_file (const char *path,
                  void *parent_baton,
                  const char *copyfrom_path,
                  svn_revnum_t copyfrom_rev,
                  void **file_baton,
                  svn_boolean_t adding, /* 0 if replacing */
                  apr_pool_t *pool)
{
  struct dir_baton *pb = parent_baton;
  struct edit_baton *eb = pb->edit_baton;
  struct file_baton *fb;
  const svn_wc_entry_t *entry;
  svn_node_kind_t kind;
  svn_wc_adm_access_t *adm_access;

  /* the file_pool can stick around for a *long* time, so we want to use
     a subpool for any temporary allocations. */
  apr_pool_t *subpool = svn_pool_create (pool);

  /* ### kff todo: if file is marked as removed by user, then flag a
     conflict in the entry and proceed.  Similarly if it has changed
     kind.  see issuezilla task #398. */

⌨️ 快捷键说明

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