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

📄 blame.c

📁 subversion-1.4.3-1.tar.gz 配置svn的源码
💻 C
📖 第 1 页 / 共 2 页
字号:
  /* Get window handler for applying delta. */  svn_txdelta_apply(last_stream, cur_stream, NULL, NULL,                    frb->currpool,                    &delta_baton->wrapped_handler,                    &delta_baton->wrapped_baton);  /* Wrap the window handler with our own. */  delta_baton->file_rev_baton = frb;  *content_delta_handler = window_handler;  *content_delta_baton = delta_baton;  /* Create the rev structure. */  frb->rev = apr_palloc(frb->mainpool, sizeof(struct rev));  if (revnum < frb->start_rev)    {      /* We shouldn't get more than one revision before start. */      assert(frb->last_filename == NULL);      /* The file existed before start_rev; generate no blame info for         lines from this revision (or before). */      frb->rev->revision = SVN_INVALID_REVNUM;      frb->rev->author = NULL;      frb->rev->date = NULL;    }  else    {      svn_string_t *str;      assert(revnum <= frb->end_rev);      /* Set values from revision props. */      frb->rev->revision = revnum;      if ((str = apr_hash_get(rev_props, SVN_PROP_REVISION_AUTHOR,                              sizeof(SVN_PROP_REVISION_AUTHOR) - 1)))        frb->rev->author = apr_pstrdup(frb->mainpool, str->data);      else        frb->rev->author = NULL;      if ((str = apr_hash_get(rev_props, SVN_PROP_REVISION_DATE,                              sizeof(SVN_PROP_REVISION_DATE) - 1)))        frb->rev->date = apr_pstrdup(frb->mainpool, str->data);      else        frb->rev->date = NULL;    }  return SVN_NO_ERROR;}static svn_error_t *old_blame(const char *target, const char *url,          svn_ra_session_t *ra_session,          struct file_rev_baton *frb);svn_error_t *svn_client_blame3(const char *target,                  const svn_opt_revision_t *peg_revision,                  const svn_opt_revision_t *start,                  const svn_opt_revision_t *end,                  const svn_diff_file_options_t *diff_options,                  svn_boolean_t ignore_mime_type,                  svn_client_blame_receiver_t receiver,                  void *receiver_baton,                  svn_client_ctx_t *ctx,                  apr_pool_t *pool){  struct file_rev_baton frb;  svn_ra_session_t *ra_session;  const char *url;  svn_revnum_t start_revnum, end_revnum;  struct blame *walk;  apr_file_t *file;  apr_pool_t *iterpool;  svn_stream_t *stream;  svn_error_t *err;  if (start->kind == svn_opt_revision_unspecified      || end->kind == svn_opt_revision_unspecified)    return svn_error_create      (SVN_ERR_CLIENT_BAD_REVISION, NULL, NULL);  else if (start->kind == svn_opt_revision_working           || end->kind == svn_opt_revision_working)    return svn_error_create      (SVN_ERR_UNSUPPORTED_FEATURE, NULL,       _("blame of the WORKING revision is not supported"));  /* Get an RA plugin for this filesystem object. */  SVN_ERR(svn_client__ra_session_from_path(&ra_session, &end_revnum,                                           &url, target, peg_revision, end,                                           ctx, pool));  SVN_ERR(svn_client__get_revision_number(&start_revnum, ra_session,                                          start, target, pool));  if (end_revnum < start_revnum)    return svn_error_create      (SVN_ERR_CLIENT_BAD_REVISION, NULL,       _("Start revision must precede end revision"));  frb.start_rev = start_revnum;  frb.end_rev = end_revnum;  frb.target = target;  frb.ctx = ctx;  frb.diff_options = diff_options;  frb.ignore_mime_type = ignore_mime_type;  frb.last_filename = NULL;  frb.blame = NULL;  frb.avail = NULL;  SVN_ERR(svn_io_temp_dir(&frb.tmp_path, pool));  frb.tmp_path = svn_path_join(frb.tmp_path, "tmp", pool),  frb.mainpool = pool;  /* The callback will flip the following two pools, because it needs     information from the previous call.  Obviously, it can't rely on     the lifetime of the pool provided by get_file_revs. */  frb.lastpool = svn_pool_create(pool);  frb.currpool = svn_pool_create(pool);  /* Collect all blame information.     We need to ensure that we get one revision before the start_rev,     if available so that we can know what was actually changed in the start     revision. */  err = svn_ra_get_file_revs(ra_session, "",                             start_revnum - (start_revnum > 0 ? 1 : 0),                             end_revnum,                             file_rev_handler, &frb, pool);    /* Fall back if it wasn't supported by the server.  Servers earlier     than 1.1 need this. */  if (err && err->apr_err == SVN_ERR_RA_NOT_IMPLEMENTED)    {      svn_error_clear(err);      err = old_blame(target, url, ra_session, &frb);    }  SVN_ERR(err);  /* Report the blame to the caller. */  /* The callback has to have been called at least once. */  assert(frb.last_filename != NULL);  /* Create a pool for the iteration below. */  iterpool = svn_pool_create(pool);  /* Open the last file and get a stream. */  SVN_ERR(svn_io_file_open(&file, frb.last_filename, APR_READ | APR_BUFFERED,                           APR_OS_DEFAULT, pool));  stream = svn_subst_stream_translated(svn_stream_from_aprfile(file, pool),                                       "\n", TRUE, NULL, FALSE, pool);  /* Process each blame item. */  for (walk = frb.blame; walk; walk = walk->next)    {      apr_off_t line_no;      for (line_no = walk->start;           !walk->next || line_no < walk->next->start;           ++line_no)        {          svn_boolean_t eof;          svn_stringbuf_t *sb;          apr_pool_clear(iterpool);          SVN_ERR(svn_stream_readline(stream, &sb, "\n", &eof, iterpool));          if (ctx->cancel_func)            SVN_ERR(ctx->cancel_func(ctx->cancel_baton));          if (!eof || sb->len)            SVN_ERR(receiver(receiver_baton, line_no, walk->rev->revision,                             walk->rev->author, walk->rev->date,                             sb->data, iterpool));          if (eof) break;        }    }  SVN_ERR(svn_stream_close(stream));  /* We don't need the temp file any more. */  SVN_ERR(svn_io_file_close(file, pool));  svn_pool_destroy(frb.lastpool);  svn_pool_destroy(frb.currpool);  svn_pool_destroy(iterpool);  return SVN_NO_ERROR;}/* svn_client_blame3 guarantees 'no EOL chars' as part of the receiver   LINE argument.  Older versions depend on the fact that if a CR is   required, that CR is already part of the LINE data.   Because of this difference, we need to trap old receivers and append   a CR to LINE before passing it on to the actual receiver on platforms   which want CRLF line termination.*/struct wrapped_receiver_baton_s{  svn_client_blame_receiver_t orig_receiver;  void *orig_baton;};static svn_error_t *wrapped_receiver(void *baton,                 apr_int64_t line_no,                 svn_revnum_t revision,                 const char *author,                 const char *date,                 const char *line,                 apr_pool_t *pool){  struct wrapped_receiver_baton_s *b = baton;  svn_stringbuf_t *expanded_line = svn_stringbuf_create(line, pool);  svn_stringbuf_appendbytes(expanded_line, "\r", 1);  return b->orig_receiver(b->orig_baton, line_no, revision, author,                          date, expanded_line->data, pool);}static voidwrap_pre_blame3_receiver(svn_client_blame_receiver_t *receiver,                   void **receiver_baton,                   apr_pool_t *pool){  if (strlen(APR_EOL_STR) > 1)    {      struct wrapped_receiver_baton_s *b = apr_palloc(pool,sizeof(*b));      b->orig_receiver = *receiver;      b->orig_baton = *receiver_baton;      *receiver_baton = b;      *receiver = wrapped_receiver;    }}svn_error_t *svn_client_blame2(const char *target,                  const svn_opt_revision_t *peg_revision,                  const svn_opt_revision_t *start,                  const svn_opt_revision_t *end,                  svn_client_blame_receiver_t receiver,                  void *receiver_baton,                  svn_client_ctx_t *ctx,                  apr_pool_t *pool){  wrap_pre_blame3_receiver(&receiver, &receiver_baton, pool);  return svn_client_blame3(target, peg_revision, start, end,                           svn_diff_file_options_create(pool), FALSE,                           receiver, receiver_baton, ctx, pool);}svn_error_t *svn_client_blame(const char *target,                 const svn_opt_revision_t *start,                 const svn_opt_revision_t *end,                 svn_client_blame_receiver_t receiver,                 void *receiver_baton,                 svn_client_ctx_t *ctx,                 apr_pool_t *pool){  wrap_pre_blame3_receiver(&receiver, &receiver_baton, pool);  return svn_client_blame2(target, end, start, end,                           receiver, receiver_baton, ctx, pool);}/* This is used when there is no get_file_revs available. */static svn_error_t *old_blame(const char *target, const char *url,          svn_ra_session_t *ra_session,          struct file_rev_baton *frb){  const char *reposURL;  struct log_message_baton lmb;  apr_array_header_t *condensed_targets;  apr_file_t *file;  svn_stream_t *stream;  struct rev *rev;  svn_node_kind_t kind;  apr_pool_t *pool = frb->mainpool;  SVN_ERR(svn_ra_check_path(ra_session, "", frb->end_rev, &kind, pool));  if (kind == svn_node_dir)    return svn_error_createf(SVN_ERR_CLIENT_IS_DIRECTORY, NULL,                             _("URL '%s' refers to a directory"), url);  condensed_targets = apr_array_make(pool, 1, sizeof(const char *));  (*((const char **)apr_array_push(condensed_targets))) = "";  SVN_ERR(svn_ra_get_repos_root(ra_session, &reposURL, pool));  /* URI decode the path before placing it in the baton, since changed_paths     passed into log_message_receiver will not be URI encoded. */  lmb.path = svn_path_uri_decode(url + strlen(reposURL), pool);  lmb.cancel_func = frb->ctx->cancel_func;  lmb.cancel_baton = frb->ctx->cancel_baton;  lmb.eldest = NULL;  lmb.pool = pool;  /* Accumulate revision metadata by walking the revisions     backwards; this allows us to follow moves/copies     correctly. */  SVN_ERR(svn_ra_get_log(ra_session,                         condensed_targets,                         frb->end_rev,                         frb->start_rev,                         0, /* no limit */                         TRUE,                         FALSE,                         log_message_receiver,                         &lmb,                         pool));  SVN_ERR(svn_client__open_ra_session_internal(&ra_session, reposURL, NULL,                                               NULL, NULL, FALSE, FALSE,                                               frb->ctx, pool));  /* Inspect the first revision's change metadata; if there are any     prior revisions, compute a new starting revision/path.  If no     revisions were selected, no blame is assigned.  A modified     item certainly has a prior revision.  It is reasonable for an     added item to have none, but anything else is unexpected.  */  if (!lmb.eldest)    {      lmb.eldest = apr_palloc(pool, sizeof(*rev));      lmb.eldest->revision = frb->end_rev;      lmb.eldest->path = lmb.path;      lmb.eldest->next = NULL;      rev = apr_palloc(pool, sizeof(*rev));      rev->revision = SVN_INVALID_REVNUM;      rev->author = NULL;      rev->date = NULL;      frb->blame = blame_create(frb, rev, 0);    }  else if (lmb.action == 'M' || SVN_IS_VALID_REVNUM(lmb.copyrev))    {      rev = apr_palloc(pool, sizeof(*rev));      if (SVN_IS_VALID_REVNUM(lmb.copyrev))        rev->revision = lmb.copyrev;      else        rev->revision = lmb.eldest->revision - 1;      rev->path = lmb.path;      rev->next = lmb.eldest;      lmb.eldest = rev;      rev = apr_palloc(pool, sizeof(*rev));      rev->revision = SVN_INVALID_REVNUM;      rev->author = NULL;      rev->date = NULL;      frb->blame = blame_create(frb, rev, 0);    }  else if (lmb.action == 'A')    {      frb->blame = blame_create(frb, lmb.eldest, 0);    }  else    return svn_error_createf(APR_EGENERAL, NULL,                             _("Revision action '%c' for "                               "revision %ld of '%s' "                               "lacks a prior revision"),                             lmb.action, lmb.eldest->revision,                             svn_path_local_style(lmb.eldest->path, pool));  /* Walk the revision list in chronological order, downloading     each fulltext, diffing it with its predecessor, and accumulating     the blame information into db.blame.  Use two iteration pools     rather than one, because the diff routines need to look at a     sliding window of revisions.  Two pools gives us a ring buffer     of sorts. */  for (rev = lmb.eldest; rev; rev = rev->next)    {      const char *tmp;      const char *temp_dir;      apr_hash_t *props;      svn_string_t *mimetype;            apr_pool_clear(frb->currpool);      SVN_ERR(svn_io_temp_dir(&temp_dir, frb->currpool));      SVN_ERR(svn_io_open_unique_file2              (&file, &tmp,               svn_path_join(temp_dir, "tmp", frb->currpool), ".tmp",               svn_io_file_del_on_pool_cleanup, frb->currpool));      stream = svn_stream_from_aprfile(file, frb->currpool);      SVN_ERR(svn_ra_get_file(ra_session, rev->path + 1, rev->revision,                              stream, NULL, &props, frb->currpool));      SVN_ERR(svn_stream_close(stream));      SVN_ERR(svn_io_file_close(file, frb->currpool));      /* If this file has a non-textual mime-type, bail out. */      if (! frb->ignore_mime_type && props &&           ((mimetype = apr_hash_get(props, SVN_PROP_MIME_TYPE,                                     sizeof(SVN_PROP_MIME_TYPE) - 1))))        {          if (svn_mime_type_is_binary(mimetype->data))            return svn_error_createf               (SVN_ERR_CLIENT_IS_BINARY_FILE, 0,               _("Cannot calculate blame information for binary file '%s'"),               svn_path_local_style(target, frb->currpool));        }      if (frb->ctx->notify_func2)        {          svn_wc_notify_t *notify            = svn_wc_create_notify(rev->path, svn_wc_notify_blame_revision,                                   pool);          notify->kind = svn_node_none;          notify->content_state = notify->prop_state            = svn_wc_notify_state_inapplicable;          notify->lock_state = svn_wc_notify_lock_state_inapplicable;          notify->revision = rev->revision;          frb->ctx->notify_func2(frb->ctx->notify_baton2, notify, pool);        }                                     if (frb->ctx->cancel_func)        SVN_ERR(frb->ctx->cancel_func(frb->ctx->cancel_baton));      if (frb->last_filename)        {          frb->rev = rev;          SVN_ERR(add_file_blame(frb->last_filename, tmp, frb));        }      frb->last_filename = tmp;      {        apr_pool_t *tmppool = frb->currpool;        frb->currpool = frb->lastpool;        frb->lastpool = tmppool;      }    }  return SVN_NO_ERROR;}

⌨️ 快捷键说明

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