Esempio n. 1
0
svn_error_t *
svn_client_revprop_set2(const char *propname,
                        const svn_string_t *propval,
                        const svn_string_t *original_propval,
                        const char *URL,
                        const svn_opt_revision_t *revision,
                        svn_revnum_t *set_rev,
                        svn_boolean_t force,
                        svn_client_ctx_t *ctx,
                        apr_pool_t *pool)
{
  svn_ra_session_t *ra_session;
  svn_boolean_t be_atomic;

  if ((strcmp(propname, SVN_PROP_REVISION_AUTHOR) == 0)
      && propval
      && strchr(propval->data, '\n') != NULL
      && (! force))
    return svn_error_create(SVN_ERR_CLIENT_REVISION_AUTHOR_CONTAINS_NEWLINE,
                            NULL, _("Author name should not contain a newline;"
                                    " value will not be set unless forced"));

  if (propval && ! svn_prop_name_is_valid(propname))
    return svn_error_createf(SVN_ERR_CLIENT_PROPERTY_NAME, NULL,
                             _("Bad property name: '%s'"), propname);

  /* Open an RA session for the URL. Note that we don't have a local
     directory, nor a place to put temp files. */
  SVN_ERR(svn_client__open_ra_session_internal(&ra_session, NULL, URL, NULL,
                                               NULL, FALSE, TRUE, ctx, pool));

  /* Resolve the revision into something real, and return that to the
     caller as well. */
  SVN_ERR(svn_client__get_revision_number(set_rev, NULL, ctx->wc_ctx, NULL,
                                          ra_session, revision, pool));

  SVN_ERR(svn_ra_has_capability(ra_session, &be_atomic,
                                SVN_RA_CAPABILITY_ATOMIC_REVPROPS, pool));
  if (be_atomic)
    {
      /* Convert ORIGINAL_PROPVAL to an OLD_VALUE_P. */
      const svn_string_t *const *old_value_p;
      const svn_string_t *unset = NULL;

      if (original_propval == NULL)
      	old_value_p = NULL;
      else if (original_propval->data == NULL)
      	old_value_p = &unset;
      else
      	old_value_p = &original_propval;

      /* The actual RA call. */
      SVN_ERR(svn_ra_change_rev_prop2(ra_session, *set_rev, propname,
                                      old_value_p, propval, pool));
    }
  else
    {
      /* The actual RA call. */
      SVN_ERR(check_and_set_revprop(set_rev, ra_session, propname,
                                    original_propval, propval, pool));
    }

  if (ctx->notify_func2)
    {
      svn_wc_notify_t *notify = svn_wc_create_notify_url(URL,
                                             propval == NULL
                                               ? svn_wc_notify_revprop_deleted
                                               : svn_wc_notify_revprop_set,
                                             pool);
      notify->prop_name = propname;
      notify->revision = *set_rev;

      (*ctx->notify_func2)(ctx->notify_baton2, notify, pool);
    }

  return SVN_NO_ERROR;
}
Esempio n. 2
0
static svn_error_t *
file_rev_handler(void *baton, const char *path, svn_revnum_t revnum,
                 apr_hash_t *rev_props,
                 svn_boolean_t merged_revision,
                 svn_txdelta_window_handler_t *content_delta_handler,
                 void **content_delta_baton,
                 apr_array_header_t *prop_diffs,
                 apr_pool_t *pool)
{
  struct file_rev_baton *frb = baton;
  svn_stream_t *last_stream;
  svn_stream_t *cur_stream;
  struct delta_baton *delta_baton;
  apr_pool_t *filepool;

  /* Clear the current pool. */
  svn_pool_clear(frb->currpool);

  /* If this file has a non-textual mime-type, bail out. */
  if (! frb->ignore_mime_type)
    SVN_ERR(check_mimetype(prop_diffs, frb->target, frb->currpool));

  if (frb->ctx->notify_func2)
    {
      svn_wc_notify_t *notify
            = svn_wc_create_notify_url(
                            svn_path_url_add_component2(frb->repos_root_url,
                                                        path+1, pool),
                            svn_wc_notify_blame_revision, pool);
      notify->path = path;
      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 = revnum;
      notify->rev_props = rev_props;
      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 there were no content changes, we couldn't care less about this
     revision now.  Note that we checked the mime type above, so things
     work if the user just changes the mime type in a commit.
     Also note that we don't switch the pools in this case.  This is important,
     since the tempfile will be removed by the pool and we need the tempfile
     from the last revision with content changes. */
  if (!content_delta_handler)
    return SVN_NO_ERROR;

  frb->merged_revision = merged_revision;

  /* Create delta baton. */
  delta_baton = apr_palloc(frb->currpool, sizeof(*delta_baton));

  /* Prepare the text delta window handler. */
  if (frb->last_filename)
    SVN_ERR(svn_stream_open_readonly(&delta_baton->source_stream, frb->last_filename,
                                     frb->currpool, pool));
  else
    /* Means empty stream below. */
    delta_baton->source_stream = NULL;
  last_stream = svn_stream_disown(delta_baton->source_stream, pool);

  if (frb->include_merged_revisions && !frb->merged_revision)
    filepool = frb->filepool;
  else
    filepool = frb->currpool;

  SVN_ERR(svn_stream_open_unique(&cur_stream, &delta_baton->filename, NULL,
                                 svn_io_file_del_on_pool_cleanup,
                                 filepool, filepool));

  /* 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_pcalloc(frb->mainpool, sizeof(struct rev));

  if (revnum < frb->start_rev)
    {
      /* We shouldn't get more than one revision before the starting
         revision (unless of including merged revisions). */
      SVN_ERR_ASSERT((frb->last_filename == NULL)
                     || frb->include_merged_revisions);

      /* The file existed before start_rev; generate no blame info for
         lines from this revision (or before). */
      frb->rev->revision = SVN_INVALID_REVNUM;
    }
  else
    {
      SVN_ERR_ASSERT(revnum <= frb->end_rev);

      /* Set values from revision props. */
      frb->rev->revision = revnum;
      frb->rev->rev_props = svn_prop_hash_dup(rev_props, frb->mainpool);
    }

  if (frb->include_merged_revisions)
    frb->rev->path = apr_pstrdup(frb->mainpool, path);

  return SVN_NO_ERROR;
}