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

📄 main.c

📁 linux subdivision ying gai ke yi le ba
💻 C
📖 第 1 页 / 共 5 页
字号:
create_unique_tmpdir (const char **name, apr_pool_t *pool)
{
  const char *unique_name;
  const char *sys_tmp_dir;
  const char *base;
  unsigned int i;

  SVN_ERR (svn_io_temp_dir (&sys_tmp_dir, pool));
  base = svn_path_join (sys_tmp_dir, "svnlook", pool);

  for (i = 1; i <= 99999; i++)
    {
      svn_error_t *err;

      unique_name = apr_psprintf (pool, "%s.%u", base, i);
      err = svn_io_dir_make (unique_name, APR_OS_DEFAULT, pool);

      if (!err)
        {
          *name = unique_name;
          return SVN_NO_ERROR;
        }

      if (! APR_STATUS_IS_EEXIST (err->apr_err))
        return err;

      svn_error_clear (err);
    }

  *name = NULL;
  return svn_error_createf (SVN_ERR_IO_UNIQUE_NAMES_EXHAUSTED,
                            NULL, _("Can't create temporary directory"));
}

/* Print some diff-y stuff in a TBD way. :-) */
static svn_error_t *
do_diff (svnlook_ctxt_t *c, apr_pool_t *pool)
{
  svn_fs_root_t *root, *base_root;
  svn_revnum_t base_rev_id;
  svn_repos_node_t *tree;

  SVN_ERR (get_root (&root, c, pool));
  if (c->is_revision)
    base_rev_id = c->rev_id - 1;
  else
    base_rev_id = svn_fs_txn_base_revision (c->txn);

  if (! SVN_IS_VALID_REVNUM (base_rev_id))
    return svn_error_createf 
      (SVN_ERR_FS_NO_SUCH_REVISION, NULL,
       _("Transaction '%s' is not based on a revision; how odd"),
       c->txn_name);
  
  SVN_ERR (generate_delta_tree (&tree, c->repos, root, base_rev_id, 
                                TRUE, pool)); 
  if (tree)
    {
      const char *tmpdir;
      svn_error_t *err;

      SVN_ERR (svn_fs_revision_root (&base_root, c->fs, base_rev_id, pool));
      SVN_ERR (create_unique_tmpdir (&tmpdir, pool));
      err = print_diff_tree (root, base_root, tree, "", "",
                             c->no_diff_deleted, tmpdir, pool);
      if (err)
        {
          svn_error_clear (svn_io_remove_dir (tmpdir, pool));
          return err;
        }
      SVN_ERR (svn_io_remove_dir (tmpdir, pool));
    }
  return SVN_NO_ERROR;
}



/* Callback baton for print_history() (and do_history()). */
struct print_history_baton
{
  svn_fs_t *fs;
  svn_boolean_t show_ids;
};

/* Implements svn_repos_history_func_t interface.  Print the history
   that's reported through this callback, possibly finding and
   displaying node-rev-ids. */
static svn_error_t *
print_history (void *baton,
               const char *path,
               svn_revnum_t revision,
               apr_pool_t *pool)
{
  struct print_history_baton *phb = baton;

  SVN_ERR (check_cancel (NULL));

  if (phb->show_ids)
    {
      const svn_fs_id_t *node_id;
      svn_fs_root_t *rev_root;
      svn_string_t *id_string;

      SVN_ERR (svn_fs_revision_root (&rev_root, phb->fs, revision, pool));
      SVN_ERR (svn_fs_node_id (&node_id, rev_root, path, pool));
      id_string = svn_fs_unparse_id (node_id, pool);
      SVN_ERR (svn_cmdline_printf (pool, "%8ld   %s <%s>\n", 
                                   revision, path, id_string->data));
    }
  else
    {
      SVN_ERR (svn_cmdline_printf (pool, "%8ld   %s\n", revision, path));
    }

  return SVN_NO_ERROR;
}


/* Print a tabular display of history location points for PATH in
   revision C->rev_id.  Optionally, SHOW_IDS.  Use POOL for
   allocations. */
static svn_error_t *
do_history (svnlook_ctxt_t *c, 
            const char *path, 
            svn_boolean_t show_ids,
            apr_pool_t *pool)
{
  struct print_history_baton args;

  if (show_ids)
    {
      SVN_ERR (svn_cmdline_printf (pool, _("REVISION   PATH <ID>\n"
                                           "--------   ---------\n")));
    }
  else
    {
      SVN_ERR (svn_cmdline_printf (pool, _("REVISION   PATH\n"
                                           "--------   ----\n")));
    }

  /* Call our history crawler.  We want the whole lifetime of the path
     (prior to the user-supplied revision, of course), across all
     copies. */
  args.fs = c->fs;
  args.show_ids = show_ids;
  SVN_ERR (svn_repos_history (c->fs, path, print_history, &args,
                              0, c->rev_id, 1, pool));
  return SVN_NO_ERROR;
}


/* Print the value of property PROPNAME on PATH in the repository.
   Error with SVN_ERR_FS_NOT_FOUND if PATH does not exist, or with
   SVN_ERR_PROPERTY_NOT_FOUND if no such property on PATH. */
static svn_error_t *
do_pget (svnlook_ctxt_t *c,
         const char *propname,
         const char *path,
         apr_pool_t *pool)
{
  svn_fs_root_t *root;
  svn_string_t *prop;
  svn_node_kind_t kind;
  svn_stream_t *stdout_stream;
  apr_size_t len;
  
  SVN_ERR (get_root (&root, c, pool));
  SVN_ERR (verify_path (&kind, root, path, pool));
  SVN_ERR (svn_fs_node_prop (&prop, root, path, propname, pool));

  if (prop == NULL)
    return svn_error_createf
      (SVN_ERR_PROPERTY_NOT_FOUND, NULL,
       _("Property '%s' not found on path '%s'"), propname, path);

  /* Else. */

  SVN_ERR (svn_stream_for_stdout (&stdout_stream, pool));
  
  /* Unlike the command line client, we don't translate the property
     value or print a trailing newline here.  We just output the raw
     bytes of whatever's in the repository, as svnlook is more likely
     to be used for automated inspections. */
  len = prop->len;
  SVN_ERR (svn_stream_write (stdout_stream, prop->data, &len));

  return SVN_NO_ERROR;
}


/* Print the property names of all properties on PATH in the repository.
   If VERBOSE, print their values too.
   Error with SVN_ERR_FS_NOT_FOUND if PATH does not exist, or with
   SVN_ERR_PROPERTY_NOT_FOUND if no such property on PATH. */
static svn_error_t *
do_plist (svnlook_ctxt_t *c,
          const char *path,
          svn_boolean_t verbose,
          apr_pool_t *pool)
{
  svn_stream_t *stdout_stream;
  svn_fs_root_t *root;
  apr_hash_t *props;
  apr_hash_index_t *hi;
  svn_node_kind_t kind;

  SVN_ERR (get_root (&root, c, pool));
  SVN_ERR (verify_path (&kind, root, path, pool));
  SVN_ERR (svn_fs_node_proplist (&props, root, path, pool));
  SVN_ERR (svn_stream_for_stdout (&stdout_stream, pool));

  for (hi = apr_hash_first (pool, props); hi; hi = apr_hash_next (hi))
    {
      const void *key;
      void *val;
      const char *pname;
      svn_string_t *propval;

      SVN_ERR (check_cancel (NULL));

      apr_hash_this (hi, &key, NULL, &val);
      pname = key;
      propval = val;

      /* Since we're already adding a trailing newline (and possible a
         colon and some spaces) anyway, just mimic the output of the
         command line client proplist.   Compare to 'svnlook propget',
         which sends the raw bytes to stdout, untranslated. */
      /* We leave printf calls here, since we don't always know the encoding
         of the prop value. */
      if (svn_prop_needs_translation (pname))
        SVN_ERR (svn_subst_detranslate_string (&propval, propval, TRUE, pool));

      if (verbose)
        {
          const char *pname_stdout;
          SVN_ERR (svn_cmdline_cstring_from_utf8 (&pname_stdout, pname, pool));
          printf ("  %s : %s\n", pname_stdout, propval->data);
        }
      else
        printf ("  %s\n", pname);
    }
  
  return SVN_NO_ERROR;
}


/* Print the diff between revision 0 and our root. */
static svn_error_t *
do_tree (svnlook_ctxt_t *c, 
         const char *path,
         svn_boolean_t show_ids, 
         apr_pool_t *pool)
{
  svn_fs_root_t *root;
  const svn_fs_id_t *id;
  svn_boolean_t is_dir;

  SVN_ERR (get_root (&root, c, pool));
  SVN_ERR (svn_fs_node_id (&id, root, path, pool));
  SVN_ERR (svn_fs_is_dir (&is_dir, root, path, pool));
  SVN_ERR (print_tree (root, path, id, is_dir, 0, show_ids, pool));
  return SVN_NO_ERROR;
}


/* Custom filesystem warning function. */
static void
warning_func (void *baton, 
              svn_error_t *err)
{
  if (! err)
    return;
  svn_handle_error (err, stderr, FALSE);
}


/* Factory function for the context baton. */
static svn_error_t *
get_ctxt_baton (svnlook_ctxt_t **baton_p,
                struct svnlook_opt_state *opt_state,
                apr_pool_t *pool)
{
  svnlook_ctxt_t *baton = apr_pcalloc (pool, sizeof (*baton));

  SVN_ERR (svn_repos_open (&(baton->repos), opt_state->repos_path, pool));
  baton->fs = svn_repos_fs (baton->repos);
  svn_fs_set_warning_func (baton->fs, warning_func, NULL);
  baton->show_ids = opt_state->show_ids;
  baton->no_diff_deleted = opt_state->no_diff_deleted;
  baton->is_revision = opt_state->txn ? FALSE : TRUE;
  baton->rev_id = opt_state->rev;
  baton->txn_name = apr_pstrdup (pool, opt_state->txn);
  if (baton->txn_name)
    SVN_ERR (svn_fs_open_txn (&(baton->txn), baton->fs, 
                              baton->txn_name, pool));
  else if (baton->rev_id == SVN_INVALID_REVNUM)
    SVN_ERR (svn_fs_youngest_rev (&(baton->rev_id), baton->fs, pool));

  *baton_p = baton;
  return SVN_NO_ERROR;
}



/*** Subcommands. ***/

/* This implements `svn_opt_subcommand_t'. */
static svn_error_t *
subcommand_author (apr_getopt_t *os, void *baton, apr_pool_t *pool)
{
  struct svnlook_opt_state *opt_state = baton;
  svnlook_ctxt_t *c;

  SVN_ERR (get_ctxt_baton (&c, opt_state, pool));
  SVN_ERR (do_author (c, pool));
  return SVN_NO_ERROR;
}

/* This implements `svn_opt_subcommand_t'. */
static svn_error_t *
subcommand_cat (apr_getopt_t *os, void *baton, apr_pool_t *pool)
{
  struct svnlook_opt_state *opt_state = baton;
  svnlook_ctxt_t *c;

  if (opt_state->arg1 == NULL)
    return svn_error_createf
      (SVN_ERR_CL_INSUFFICIENT_ARGS, NULL,
       _("Missing repository path argument"));

  SVN_ERR (get_ctxt_baton (&c, opt_state, pool));
  SVN_ERR (do_cat (c, opt_state->arg1, pool));
  return SVN_NO_ERROR;
}

/* This implements `svn_opt_subcommand_t'. */
static svn_error_t *
subcommand_changed (apr_getopt_t *os, void *baton, apr_pool_t *pool)
{
  struct svnlook_opt_state *opt_state = baton;
  svnlook_ctxt_t *c;

  SVN_ERR (get_ctxt_baton (&c, opt_state, pool));
  SVN_ERR (do_changed (c, pool));
  return SVN_NO_ERROR;
}

/* This implements `svn_opt_subcommand_t'. */
static svn_error_t *
subcommand_date (apr_getopt_t *os, void *baton, apr_pool_t *pool)
{
  struct svnlook_opt_state *opt_state = baton;
  svnlook_ctxt_t *c;

  SVN_ERR (get_ctxt_baton (&c, opt_state, pool));
  SVN_ERR (do_date (c, pool));
  return SVN_NO_ERROR;
}

/* This implements `svn_opt_subcommand_t'. */
static svn_error_t *
subcommand_diff (apr_getopt_t *os, void *baton, apr_pool_t *pool)
{
  struct svnlook_opt_state *opt_state = baton;
  svnlook_ctxt_t *c;

  SVN_ERR (get_ctxt_baton (&c, opt_state, pool));
  SVN_ERR (do_diff (c, pool));
  return SVN_NO_ERROR;
}

/* This implements `svn_opt_subcommand_t'. */
static svn_error_t *
subcommand_dirschanged (apr_getopt_t *os, void *baton, apr_pool_t *pool)
{
  struct svnlook_opt_state *opt_state = baton;
  svnlook_ctxt_t *c;

  SVN_ERR (get_ctxt_baton (&c, opt_state, pool));
  SVN_ERR (do_dirs_changed (c, pool));
  return SVN_NO_ERROR;
}

/* This implements `svn_opt_subcommand_t'. */
static svn_error_t *
subcommand_help (apr_getopt_t *os, void *baton, apr_pool_t *pool)
{
  struct svnlook_opt_state *opt_state = baton;
  const char *header =
    _("general usage: svnlook SUBCOMMAND REPOS_PATH [ARGS & OPTIONS ...]\n"
      "Note: any subcommand which takes the '--revision' and '--transaction'\n"
      "      options will, if invoked without one of those options, act on\n"
      "      the repository's youngest revision.\n"
      "Type \"svnlook help <subcommand>\" for help on a specific subcommand.\n"
      "\n"
      "Available subcommands:\n");

  SVN_ERR (svn_opt_print_help (os, "svnlook", 
                               opt_state ? opt_state->version : FALSE, 
                               FALSE, NULL,
                               header, cmd_table, options_table, NULL,
                               pool));
  
  return SVN_NO_ERROR;
}

/* This implements `svn_opt_subcommand_t'. */
static svn_error_t *
subcommand_history (apr_getopt_t *os, void *baton, apr_pool_t *pool)
{
  struct svnlook_opt_state *opt_state = baton;
  svnlook_ctxt_t *c;
  const char *path = "/";

  if (opt_state->arg1)
    path = opt_state->arg1;

  SVN_ERR (get_ctxt_baton (&c, opt_state, pool));
  SVN_ERR (do_history (c, path, opt_state->show_ids, pool));
  return SVN_NO_ERROR;
}

⌨️ 快捷键说明

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