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

📄 diff.c

📁 linux subdivision ying gai ke yi le ba
💻 C
📖 第 1 页 / 共 5 页
字号:
    path2 = apr_psprintf (subpool, "%s\t(...%s)", path, path2);
  else
    path2 = apr_psprintf (subpool, "%s\t(.../%s)", path, path2);
  
  label1 = diff_label (path1, rev1, subpool);
  label2 = diff_label (path2, rev2, subpool);

  /* Possible easy-out: if either mime-type is binary, don't attempt
     to generate a viewable diff at all.   Print a warning and exit. */
  if (mimetype1)
    mt1_binary = svn_mime_type_is_binary (mimetype1);
  if (mimetype2)
    mt2_binary = svn_mime_type_is_binary (mimetype2);

  if (mt1_binary || mt2_binary)
    {
      /* Print out the diff header. */
      SVN_ERR (svn_stream_printf (os, subpool,
                                  "Index: %s" APR_EOL_STR
                                  "%s" APR_EOL_STR, path, equal_string));

      SVN_ERR (svn_stream_printf
               (os, subpool,
                _("Cannot display: file marked as a binary type.%s"),
                APR_EOL_STR));
      
      if (mt1_binary && !mt2_binary)
        SVN_ERR (svn_stream_printf (os, subpool,
                                    "svn:mime-type = %s" APR_EOL_STR,
                                    mimetype1));
      else if (mt2_binary && !mt1_binary)
        SVN_ERR (svn_stream_printf (os, subpool,
                                    "svn:mime-type = %s" APR_EOL_STR,
                                    mimetype2));
      else if (mt1_binary && mt2_binary)
        {
          if (strcmp (mimetype1, mimetype2) == 0)
            SVN_ERR (svn_stream_printf
                     (os, subpool,
                      "svn:mime-type = %s" APR_EOL_STR,
                      mimetype1));
          else
            SVN_ERR (svn_stream_printf
                     (os, subpool,
                      "svn:mime-type = (%s, %s)" APR_EOL_STR,
                      mimetype1, mimetype2));
        }

      /* Exit early. */
      if (state)
        *state = svn_wc_notify_state_unknown;
      svn_pool_destroy (subpool);
      return SVN_NO_ERROR;
    }


  /* Find out if we need to run an external diff */
  if (diff_cmd_baton->config)
    {
      svn_config_t *cfg = apr_hash_get (diff_cmd_baton->config,
                                        SVN_CONFIG_CATEGORY_CONFIG,
                                        APR_HASH_KEY_STRING);
      svn_config_get (cfg, &diff_cmd, SVN_CONFIG_SECTION_HELPERS,
                      SVN_CONFIG_OPTION_DIFF_CMD, NULL);
    }

  if (diff_cmd)
    {
      /* Print out the diff header. */
      SVN_ERR (svn_stream_printf (os, subpool,
                                  "Index: %s" APR_EOL_STR
                                  "%s" APR_EOL_STR, path, equal_string));
      /* Close the stream (flush) */
      SVN_ERR (svn_stream_close (os));

      SVN_ERR (svn_io_run_diff (".", args, nargs, label1, label2,
                                tmpfile1, tmpfile2, 
                                &exitcode, diff_cmd_baton->outfile, errfile,
                                diff_cmd, subpool));
    }
  else   /* use libsvn_diff to generate the diff  */
    {
      svn_diff_t *diff;

      /* We don't currently support any options (well, other than -u, since we 
         default to unified diff output anyway), so if we received anything 
         other than that it's an error. */
      if (diff_cmd_baton->options)
        {
          for (i = 0; i < diff_cmd_baton->options->nelts; ++i)
            {
              const char *arg
                = ((const char **)(diff_cmd_baton->options->elts))[i];

              if (strcmp(arg, "-u") == 0)
                continue;
              else
                return svn_error_createf(SVN_ERR_INVALID_DIFF_OPTION, NULL,
                                         _("'%s' is not supported"), arg);
            }
        }

      SVN_ERR (svn_diff_file_diff (&diff, tmpfile1, tmpfile2, subpool));

      if (svn_diff_contains_diffs (diff) || diff_cmd_baton->force_diff_output)
        {
          /* Print out the diff header. */
          SVN_ERR (svn_stream_printf (os, subpool,
                                      "Index: %s" APR_EOL_STR
                                      "%s" APR_EOL_STR, path, equal_string));

          /* Output the actual diff */
          SVN_ERR (svn_diff_file_output_unified (os, diff,
                                                 tmpfile1, tmpfile2,
                                                 label1, label2,
                                                 subpool));
        }
    }

  /* ### todo: someday we'll need to worry about whether we're going
     to need to write a diff plug-in mechanism that makes use of the
     two paths, instead of just blindly running SVN_CLIENT_DIFF.  */

  if (state)
    *state = svn_wc_notify_state_unknown;

  /* Destroy the subpool. */
  svn_pool_destroy (subpool);

  return SVN_NO_ERROR;
}

/* The because the repos-diff editor passes at least one empty file to
   each of these next two functions, they can be dumb wrappers around
   the main workhorse routine. */
static svn_error_t *
diff_file_added (svn_wc_adm_access_t *adm_access,
                 svn_wc_notify_state_t *state,
                 const char *path,
                 const char *tmpfile1,
                 const char *tmpfile2,
                 svn_revnum_t rev1,
                 svn_revnum_t rev2,
                 const char *mimetype1,
                 const char *mimetype2,
                 void *diff_baton)
{
  struct diff_cmd_baton *diff_cmd_baton = diff_baton;

  /* We want diff_file_changed to unconditionally show diffs, even if
     the diff is empty (as would be the case if an empty file were
     added.)  It's important, because 'patch' would still see an empty
     diff and create an empty file.  It's also important to let the
     user see that *something* happened. */
  diff_cmd_baton->force_diff_output = TRUE;

  SVN_ERR (diff_file_changed (adm_access, state, path, tmpfile1, tmpfile2, 
                              rev1, rev2,
                              mimetype1, mimetype2, diff_baton));
  
  diff_cmd_baton->force_diff_output = FALSE;

  return SVN_NO_ERROR;
}

static svn_error_t *
diff_file_deleted_with_diff (svn_wc_adm_access_t *adm_access,
                             svn_wc_notify_state_t *state,
                             const char *path,
                             const char *tmpfile1,
                             const char *tmpfile2,
                             const char *mimetype1,
                             const char *mimetype2,
                             void *diff_baton)
{
  struct diff_cmd_baton *diff_cmd_baton = diff_baton;

  return diff_file_changed (adm_access, state, path, tmpfile1, tmpfile2, 
                            diff_cmd_baton->revnum1, diff_cmd_baton->revnum2,
                            mimetype1, mimetype2, diff_baton);
}

static svn_error_t *
diff_file_deleted_no_diff (svn_wc_adm_access_t *adm_access,
                           svn_wc_notify_state_t *state,
                           const char *path,
                           const char *tmpfile1,
                           const char *tmpfile2,
                           const char *mimetype1,
                           const char *mimetype2,
                           void *diff_baton)
{
  struct diff_cmd_baton *diff_cmd_baton = diff_baton;

  if (state)
    *state = svn_wc_notify_state_unknown;

  SVN_ERR (file_printf_from_utf8
           (diff_cmd_baton->outfile,
            "Index: %s (deleted)" APR_EOL_STR "%s" APR_EOL_STR, 
            path, equal_string));

  return SVN_NO_ERROR;
}

/* For now, let's have 'svn diff' send feedback to the top-level
   application, so that something reasonable about directories and
   propsets gets printed to stdout. */
static svn_error_t *
diff_dir_added (svn_wc_adm_access_t *adm_access,
                svn_wc_notify_state_t *state,
                const char *path,
                svn_revnum_t rev,
                void *diff_baton)
{
  if (state)
    *state = svn_wc_notify_state_unknown;

  /* ### todo:  send feedback to app */
  return SVN_NO_ERROR;
}

static svn_error_t *
diff_dir_deleted (svn_wc_adm_access_t *adm_access,
                  svn_wc_notify_state_t *state,
                  const char *path,
                  void *diff_baton)
{
  if (state)
    *state = svn_wc_notify_state_unknown;

  return SVN_NO_ERROR;
}
  
static svn_error_t *
diff_props_changed (svn_wc_adm_access_t *adm_access,
                    svn_wc_notify_state_t *state,
                    const char *path,
                    const apr_array_header_t *propchanges,
                    apr_hash_t *original_props,
                    void *diff_baton)
{
  struct diff_cmd_baton *diff_cmd_baton = diff_baton;
  apr_array_header_t *props;
  apr_pool_t *subpool = svn_pool_create (diff_cmd_baton->pool);

  SVN_ERR (svn_categorize_props (propchanges, NULL, NULL, &props, subpool));

  if (props->nelts > 0)
    SVN_ERR (display_prop_diffs (props, original_props, path,
                                 diff_cmd_baton->outfile, subpool));

  if (state)
    *state = svn_wc_notify_state_unknown;

  svn_pool_destroy (subpool);
  return SVN_NO_ERROR;
}


/*-----------------------------------------------------------------*/

/*** Callbacks for 'svn merge', invoked by the repos-diff editor. ***/


struct merge_cmd_baton {
  svn_boolean_t force;
  svn_boolean_t dry_run;
  const char *target;                 /* Working copy target of merge */
  const char *url;                    /* The second URL in the merge */
  const char *path;                   /* The wc path of the second target, this
                                         can be NULL if we don't have one. */
  const svn_opt_revision_t *revision; /* Revision of second URL in the merge */
  svn_client_ctx_t *ctx;

  /* The diff3_cmd in ctx->config, if any, else null.  We could just
     extract this as needed, but since more than one caller uses it,
     we just set it up when this baton is created. */
  const char *diff3_cmd;

  apr_pool_t *pool;
};


static svn_error_t *
merge_file_changed (svn_wc_adm_access_t *adm_access,
                    svn_wc_notify_state_t *state,
                    const char *mine,
                    const char *older,
                    const char *yours,
                    svn_revnum_t older_rev,
                    svn_revnum_t yours_rev,
                    const char *mimetype1,
                    const char *mimetype2,
                    void *baton)
{
  struct merge_cmd_baton *merge_b = baton;
  apr_pool_t *subpool = svn_pool_create (merge_b->pool);
  /* xgettext: the '.working', '.merge-left.r%ld' and '.merge-right.r%ld'
     strings are used to tag onto a filename in case of a merge conflict */
  const char *target_label = _(".working");
  const char *left_label = apr_psprintf (subpool,
                                         _(".merge-left.r%ld"),
                                         older_rev);
  const char *right_label = apr_psprintf (subpool,
                                          _(".merge-right.r%ld"),
                                          yours_rev);
  svn_boolean_t has_local_mods;
  svn_boolean_t merge_required = TRUE;
  enum svn_wc_merge_outcome_t merge_outcome;

  /* Easy out:  no access baton means there ain't no merge target */
  if (adm_access == NULL)
    {
      if (state)
        *state = svn_wc_notify_state_missing;
      return SVN_NO_ERROR;
    }
  
  /* Other easy outs:  if the merge target isn't under version
     control, or is just missing from disk, fogettaboutit.  There's no
     way svn_wc_merge() can do the merge. */
  {
    const svn_wc_entry_t *entry;
    svn_node_kind_t kind;

    SVN_ERR (svn_wc_entry (&entry, mine, adm_access, FALSE, subpool));
    SVN_ERR (svn_io_check_path (mine, &kind, subpool));

    /* ### a future thought:  if the file is under version control,
       but the working file is missing, maybe we can 'restore' the
       working file from the text-base, and then allow the merge to run?  */

    if ((! entry) || (kind != svn_node_file))
      {
        if (state)
          *state = svn_wc_notify_state_missing;
        return SVN_NO_ERROR;
      }
  }

  /* This callback is essentially no more than a wrapper around
     svn_wc_merge().  Thank goodness that all the
     diff-editor-mechanisms are doing the hard work of getting the
     fulltexts! */

  SVN_ERR (svn_wc_text_modified_p (&has_local_mods, mine, FALSE,
                                   adm_access, subpool));

  /* Special case:  if a binary file isn't locally modified, and is
     exactly identical to the 'left' side of the merge, then don't
     allow svn_wc_merge to produce a conflict.  Instead, just
     overwrite the working file with the 'right' side of the merge. */
  if ((! has_local_mods)
      && ((mimetype1 && svn_mime_type_is_binary (mimetype1))
          || (mimetype2 && svn_mime_type_is_binary (mimetype2))))
    {
      svn_boolean_t same_contents;

⌨️ 快捷键说明

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