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

📄 main.c

📁 linux subdivision ying gai ke yi le ba
💻 C
📖 第 1 页 / 共 5 页
字号:

  /* Return here if the node has no children. */
  tmp_node = node->child;
  if (! tmp_node)
    return SVN_NO_ERROR;

  /* Recursively handle the node's children. */
  subpool = svn_pool_create (pool);  
  full_path = svn_path_join (path, tmp_node->name, subpool);
  SVN_ERR (print_dirs_changed_tree (tmp_node, full_path, subpool));
  while (tmp_node->sibling)
    {
      svn_pool_clear (subpool);
      tmp_node = tmp_node->sibling;
      full_path = svn_path_join (path, tmp_node->name, subpool);
      SVN_ERR (print_dirs_changed_tree (tmp_node, full_path, subpool));
    }
  svn_pool_destroy (subpool);

  return SVN_NO_ERROR;
}


/* Recursively print all nodes in the tree that have been modified
   (do not include directories affected only by "bubble-up"). */
static svn_error_t *
print_changed_tree (svn_repos_node_t *node,
                    const char *path /* UTF-8! */,
                    apr_pool_t *pool)
{
  const char *full_path;
  char status[3] = "_ ";
  int print_me = 1;
  apr_pool_t *subpool;

  SVN_ERR (check_cancel (NULL));

  if (! node)
    return SVN_NO_ERROR;

  /* Print the node. */
  if (node->action == 'A')
    status[0] = 'A';
  else if (node->action == 'D')
    status[0] = 'D';
  else if (node->action == 'R')
    {
      if ((! node->text_mod) && (! node->prop_mod))
        print_me = 0;
      if (node->text_mod)
        status[0] = 'U';
      if (node->prop_mod)
        status[1] = 'U';
    }
  else
    print_me = 0;

  /* Print this node unless told to skip it. */
  if (print_me)
    {
      SVN_ERR (svn_cmdline_printf (pool, "%s  %s%s\n",
                                   status,
                                   path,
                                   node->kind == svn_node_dir ? "/" : ""));
    }
  
  /* Return here if the node has no children. */
  node = node->child;
  if (! node)
    return SVN_NO_ERROR;

  /* Recursively handle the node's children. */
  subpool = svn_pool_create (pool);  
  full_path = svn_path_join (path, node->name, subpool);
  SVN_ERR (print_changed_tree (node, full_path, subpool));
  while (node->sibling)
    {
      svn_pool_clear (subpool);
      node = node->sibling;
      full_path = svn_path_join (path, node->name, subpool);
      SVN_ERR (print_changed_tree (node, full_path, subpool));
    }
  svn_pool_destroy (subpool);

  return SVN_NO_ERROR;
}


static svn_error_t *
open_writable_binary_file (apr_file_t **fh, 
                           const char *path /* UTF-8! */, 
                           apr_pool_t *pool)
{
  apr_array_header_t *path_pieces;
  svn_error_t *err;
  int i;
  const char *full_path, *dir;
  
  /* Try the easy way to open the file. */
  err = svn_io_file_open (fh, path, 
                          APR_WRITE | APR_CREATE | APR_TRUNCATE | APR_BINARY,
                          APR_OS_DEFAULT, pool);
  if (! err)
    return SVN_NO_ERROR;

  svn_path_split (path, &dir, NULL, pool);

  /* If the file path has no parent, then we've already tried to open
     it as best as we care to try above. */
  if (svn_path_is_empty (dir))
    return err;

  path_pieces = svn_path_decompose (dir, pool);
  if (! path_pieces->nelts)
    return SVN_NO_ERROR;

  full_path = "";
  for (i = 0; i < path_pieces->nelts; i++)
    {
      svn_node_kind_t kind;
      const char *piece = ((const char **) (path_pieces->elts))[i];
      full_path = svn_path_join (full_path, piece, pool);
      SVN_ERR (svn_io_check_resolved_path (full_path, &kind, pool));

      /* Does this path component exist at all? */
      if (kind == svn_node_none)
        {
          SVN_ERR (svn_io_dir_make (full_path, APR_OS_DEFAULT, pool));
        }
      else if (kind != svn_node_dir)
        {
          return svn_error_createf (err->apr_err, err,
                                    "Error creating dir '%s' (path exists)", 
                                    full_path);
        }
    }

  /* Now that we are ensured that the parent path for this file
     exists, try once more to open it. */
  svn_error_clear (err);
  return svn_io_file_open (fh, path, 
                           APR_WRITE | APR_CREATE | APR_TRUNCATE | APR_BINARY,
                           APR_OS_DEFAULT, pool);
}


static svn_error_t *
dump_contents (apr_file_t *fh,
               svn_fs_root_t *root,
               const char *path /* UTF-8! */,
               apr_pool_t *pool)
{
  svn_stream_t *contents, *file_stream;

  /* Grab the contents and copy them into fh. */
  SVN_ERR (svn_fs_file_contents (&contents, root, path, pool));
  file_stream = svn_stream_from_aprfile (fh, pool);
  SVN_ERR (svn_stream_copy (contents, file_stream, pool));
  return SVN_NO_ERROR;
}


/* Prepare temporary files *TMPFILE1 and *TMPFILE2 for diffing
   PATH1@ROOT1 versus PATH2@ROOT2.  If either ROOT1 or ROOT2 is NULL,
   the temporary file for its path/root will be an empty one.
   Otherwise, its temporary file will contain the contents of that
   path/root in the repository.

   An exception to this is when either path/root has an svn:mime-type
   property set on it which indicates that the file contains
   non-textual data -- in this case, the *IS_BINARY flag is set and no
   temporary files are created.

   Use POOL for all that allocation goodness. */
static svn_error_t *
prepare_tmpfiles (const char **tmpfile1,
                  const char **tmpfile2,
                  svn_boolean_t *is_binary,
                  svn_fs_root_t *root1,
                  const char *path1,
                  svn_fs_root_t *root2,
                  const char *path2,
                  const char *tmpdir,
                  apr_pool_t *pool)
{
  svn_string_t *mimetype;
  apr_file_t *fh;

  /* Init the return values. */
  *tmpfile1 = NULL;
  *tmpfile2 = NULL;
  *is_binary = FALSE;

  assert (path1 && path2);

  /* Check for binary mimetypes.  If either file has a binary
     mimetype, get outta here.  */
  if (root1)
    {
      SVN_ERR (svn_fs_node_prop (&mimetype, root1, path1, 
                                 SVN_PROP_MIME_TYPE, pool));
      if (mimetype && svn_mime_type_is_binary (mimetype->data))
        {
          *is_binary = TRUE;
          return SVN_NO_ERROR;
        }
    }
  if (root2)
    {
      SVN_ERR (svn_fs_node_prop (&mimetype, root2, path2, 
                                 SVN_PROP_MIME_TYPE, pool));
      if (mimetype && svn_mime_type_is_binary (mimetype->data))
        {
          *is_binary = TRUE;
          return SVN_NO_ERROR;
        }
    }

  /* Now, prepare the two temporary files, each of which will either
     be empty, or will have real contents.  The first file we will
     make in our temporary directory. */
  *tmpfile2 = svn_path_join (tmpdir, path2, pool);
  SVN_ERR (open_writable_binary_file (&fh, *tmpfile2, pool));
  if (root2)
    SVN_ERR (dump_contents (fh, root2, path2, pool));
  apr_file_close (fh);

  /* The second file is constructed from the first one's path. */
  SVN_ERR (svn_io_open_unique_file (&fh, tmpfile1, *tmpfile2, 
                                    NULL, FALSE, pool));
  if (root1)
    SVN_ERR (dump_contents (fh, root1, path1, pool));
  apr_file_close (fh);

  return SVN_NO_ERROR;
}


/* Generate a diff label for PATH in ROOT, allocating in POOL. */
static svn_error_t *
generate_label (const char **label,
                svn_fs_root_t *root,
                const char *path,
                apr_pool_t *pool)
{
  svn_fs_t *fs = svn_fs_root_fs (root);
  svn_string_t *date;
  const char *datestr;
  const char *name = NULL;
  svn_revnum_t rev = SVN_INVALID_REVNUM;

  if (svn_fs_is_revision_root (root))
    {
      rev = svn_fs_revision_root_revision (root);
      SVN_ERR (svn_fs_revision_prop (&date, fs, rev, 
                                     SVN_PROP_REVISION_DATE, pool));
    }
  else 
    {
      svn_fs_txn_t *txn;
      name = svn_fs_txn_root_name (root, pool);
      SVN_ERR (svn_fs_open_txn (&txn, fs, name, pool));
      SVN_ERR (svn_fs_txn_prop (&date, txn, SVN_PROP_REVISION_DATE, pool));
    }
  
  if (date)
    {
      datestr = date->data;
      ((char *)datestr)[10] = ' ';
      ((char *)datestr)[19] = '\0';
    }
  else
    {
      datestr = "                      ";
    }

  if (name)
    *label = apr_psprintf (pool, "%s\t%s UTC (txn %s)", 
                           path, datestr, name); 
  else
    *label = apr_psprintf (pool, "%s\t%s UTC (rev %ld)",
                           path, datestr, rev);
  return SVN_NO_ERROR;
}


/*
 * Constant diff output separator strings
 */
static const char equal_string[] = 
  "===================================================================";
static const char under_string[] =
  "___________________________________________________________________";


/* Helper function to display differences in properties of a file */
static svn_error_t *
display_prop_diffs (const apr_array_header_t *prop_diffs,
                    apr_hash_t *orig_props,
                    const char *path,
                    apr_pool_t *pool)
{
  int i;

  SVN_ERR (svn_cmdline_printf (pool, "\nProperty changes on: %s\n%s\n",
                               path, under_string));

  for (i = 0; i < prop_diffs->nelts; i++)
    {
      const svn_string_t *orig_value;
      const svn_prop_t *pc = &APR_ARRAY_IDX (prop_diffs, i, svn_prop_t);

      SVN_ERR (check_cancel (NULL));

      if (orig_props)
        orig_value = apr_hash_get (orig_props, pc->name, APR_HASH_KEY_STRING);
      else
        orig_value = NULL;

      SVN_ERR (svn_cmdline_printf (pool, _("Name: %s\n"), pc->name));

      /* For now, we have a rather simple heuristic: if this is an
         "svn:" property, then assume the value is UTF-8 and must
         therefore be converted before printing.  Otherwise, just
         print whatever's there and hope for the best.
         ### We don't use svn_cmdline_printf here, since we don't know if the
         values are UTF-8. */
      {
        svn_boolean_t val_to_utf8 = svn_prop_is_svn_prop (pc->name);
        const char *printable_val;

        if (orig_value != NULL)
          {
            if (val_to_utf8)
              SVN_ERR (svn_cmdline_cstring_from_utf8 (&printable_val, 
                                                      orig_value->data, pool));
            else
              printable_val = orig_value->data;
            printf ("   - %s\n", printable_val);
          }

        if (pc->value != NULL)
          {
            if (val_to_utf8)
              SVN_ERR (svn_cmdline_cstring_from_utf8
                       (&printable_val, pc->value->data, pool));
            else
              printable_val = pc->value->data;
            printf ("   + %s\n", printable_val);
          }
      }
    }

  SVN_ERR (svn_cmdline_printf (pool, "\n"));
  return svn_cmdline_fflush (stdout);
}



/* Recursively print all nodes in the tree that have been modified
   (do not include directories affected only by "bubble-up"). */
static svn_error_t *
print_diff_tree (svn_fs_root_t *root,
                 svn_fs_root_t *base_root,
                 svn_repos_node_t *node, 
                 const char *path /* UTF-8! */,
                 const char *base_path /* UTF-8! */,
                 svn_boolean_t no_diff_deleted,
                 const char *tmpdir,
                 apr_pool_t *pool)
{
  const char *orig_path = NULL, *new_path = NULL;
  svn_boolean_t do_diff = FALSE;
  svn_boolean_t is_copy = FALSE;
  svn_boolean_t binary = FALSE;
  apr_pool_t *subpool;

  SVN_ERR (check_cancel (NULL));

  if (! node)
    return SVN_NO_ERROR;

  /* Print copyfrom history for the top node of a copied tree. */
  if ((SVN_IS_VALID_REVNUM (node->copyfrom_rev))
      && (node->copyfrom_path != NULL))
    {
      /* This is ... a copy. */
      is_copy = TRUE;

      /* Propagate the new base.  Copyfrom paths usually start with a
         slash; we remove it for consistency with the target path.
         ### Yes, it would be *much* better for something in the path
             library to be taking care of this! */
      if (node->copyfrom_path[0] == '/')
        base_path = apr_pstrdup (pool, node->copyfrom_path + 1);
      else
        base_path = apr_pstrdup (pool, node->copyfrom_path);

      SVN_ERR (svn_cmdline_printf (pool, _("Copied: %s (from rev %ld, %s)\n"),
                                   path, node->copyfrom_rev, base_path));

      SVN_ERR (svn_fs_revision_root (&base_root,
                                     svn_fs_root_fs (base_root),
                                     node->copyfrom_rev, pool));
    }

  /*** First, we'll just print file content diffs. ***/
  if (node->kind == svn_node_file)
    {
      /* Here's the generalized way we do our diffs:

         - First, we'll check for svn:mime-type properties on the old
           and new files.  If either has such a property, and it
           represents a binary type, we won't actually be doing a real
           diff.
           
         - First, dump the contents of the new version of the file
           into the svnlook temporary directory, building out the
           actual directories that need to be created in order to
           fully represent the filesystem path inside the tmp
           directory.

⌨️ 快捷键说明

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