Changeset 318 for trunk/lib/SVN.cc


Ignore:
Timestamp:
May 18, 2007, 11:35:45 AM (14 years ago)
Author:
Jari Häkkinen
Message:

Fixes #167 and addresses #74. Interfaces have changed. SVN::instance usage has changed, read SVN class documentation.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/lib/SVN.cc

    r305 r318  
    4747
    4848
    49   SVN::SVN(void)
     49  SVN::SVN(const std::string& path)
    5050    : adm_access_(NULL), allocator_(NULL), context_(NULL), pool_(NULL)
    5151  {
     
    5858    // memorywise but what about APR internal counters?)
    5959    if (svn_cmdline_init("svndigest",stderr) != EXIT_SUCCESS)
    60       throw SVNException("SVN(void): svn_cmdline_init failed");
     60      throw SVNException("SVN: svn_cmdline_init failed");
    6161
    6262    /// create top-level pool
    6363    if (apr_allocator_create(&allocator_))
    64       throw SVNException("SVN(void): apr_allocator_create failed");
     64      throw SVNException("SVN(_allocator_create failed");
    6565    apr_allocator_max_free_set(allocator_,SVN_ALLOCATOR_RECOMMENDED_MAX_FREE);
    6666    pool_ = svn_pool_create_ex(NULL, allocator_);
     
    6969    // initialize the repository access library
    7070    if ((err=svn_ra_initialize(pool_)))
    71       cleanup_failed_init(err, "SVN(void): svn_ra_initialize failed");
     71      cleanup_failed_init(err, "SVN: svn_ra_initialize failed");
    7272
    7373    // Check that users .subversion exist. Should this really be done?
     
    7676    // stuff (compare with the svn binary).
    7777    if ((err=svn_config_ensure(NULL, pool_)))
    78       cleanup_failed_init(err, "SVN(void): svn_config_ensure failed");
     78      cleanup_failed_init(err, "SVN: svn_config_ensure failed");
    7979
    8080    // create a client context object
    8181    if ((err=svn_client_create_context(&context_, pool_)))
    82       cleanup_failed_init(err, "SVN(void): svn_client_create_context failed");
     82      cleanup_failed_init(err, "SVN: svn_client_create_context failed");
    8383
    8484    if ((err=svn_config_get_config(&(context_->config), NULL, pool_)))
    85       cleanup_failed_init(err, "SVN(void): svn_config_get_config failed");
     85      cleanup_failed_init(err, "SVN: svn_config_get_config failed");
    8686
    8787    // set up authentication stuff
     
    9393                                          context_->cancel_func,
    9494                                          context_->cancel_baton, pool_)))
    95       cleanup_failed_init(err, "SVN(void): svn_cmdline_setup_auth_baton failed");
     95      cleanup_failed_init(err, "SVN: svn_cmdline_setup_auth_baton failed");
     96
     97    // Set up svn administration area access. The whole structure is
     98    // setup, maybe this is unnecessary?
     99    const char* canonical_path=svn_path_internal_style(path.c_str(), pool_);
     100    if (svn_error_t *err=svn_wc_adm_open3(&adm_access_, NULL, canonical_path,
     101                                          false, -1, context_->cancel_func,
     102                                          context_->cancel_baton, pool_))
     103      cleanup_failed_init(err, "SVN: svn_wc_adm_open3 failed");
     104
     105    // get a session to the repository
     106    struct root_url_receiver_baton rurb;
     107    client_info(path, root_url_receiver, static_cast<void*>(&rurb));
     108    if (svn_error_t *err=svn_client_open_ra_session(&ra_session_,
     109                                                    rurb.path.c_str(),
     110                                                    context_, pool_))
     111      cleanup_failed_init(err, "SVN: svn_client_open_ra_session failed");
    96112  }
    97113
     
    108124
    109125
     126  void SVN::cleanup(svn_error_t *err,apr_pool_t *pool,
     127                    const std::string& message)
     128  {
     129    svn_handle_error2(err,stderr,false,"svndigest: ");
     130    svn_error_clear(err);
     131    if (pool)
     132      svn_pool_destroy(pool);
     133    if (message.length()>0)
     134      throw SVNException(message);
     135  }
     136
     137
     138  void SVN::cleanup_failed_init(svn_error_t *err, const std::string& message)
     139  {
     140    cleanup(err,pool_);
     141    apr_allocator_destroy(allocator_);
     142    throw SVNException(message);
     143  }
     144
     145
    110146  svn_error_t* SVN::client_blame(const std::string& path,
    111147                                 svn_client_blame_receiver_t receiver,
     
    117153    start.kind=svn_opt_revision_number;
    118154    start.value.number=0;
    119     head.kind=svn_opt_revision_head;
     155    head.kind = ( svn_path_is_url(path.c_str()) ?
     156                  svn_opt_revision_head : svn_opt_revision_base );
    120157    apr_pool_t *subpool = svn_pool_create(pool_);
    121158    svn_error_t* err=svn_client_blame3(path.c_str(), &peg, &start, &head,
     
    143180
    144181
     182  void SVN::client_log(const std::string& path,
     183                       svn_log_message_receiver_t receiver, void *baton)
     184  {
     185    // Allocate space in subpool to pool_ for apr_path (here a string).
     186    apr_pool_t *subpool = svn_pool_create(pool_);
     187    apr_array_header_t* apr_path=apr_array_make(subpool,1,4);
     188    // Copy path to apr_path.
     189    (*((const char **) apr_array_push(apr_path))) =
     190      apr_pstrdup(subpool, svn_path_internal_style(path.c_str(),subpool));
     191
     192    // Setup to retrieve all commit logs.
     193    svn_opt_revision_t peg, start, head;
     194    peg.kind=svn_opt_revision_unspecified;
     195    start.kind=svn_opt_revision_number;
     196    start.value.number=0;
     197    head.kind = ( svn_path_is_url(path.c_str()) ?
     198                  svn_opt_revision_head : svn_opt_revision_base );
     199    svn_error_t* err=NULL;
     200    if ((err=svn_client_log3(apr_path, &peg, &start, &head, 0, false, false,
     201                             receiver, baton, context_, subpool)))
     202      // cleanupp will throw an exception
     203      cleanup(err, subpool, "commit_dates: svn_client_log3 failed");
     204    svn_pool_destroy(subpool);
     205  }
     206
     207
    145208  void SVN::client_proplist(const std::string& path,
    146209                            std::map<std::string, std::string>& property)
     
    148211    svn_opt_revision_t peg, revision;
    149212    peg.kind=svn_opt_revision_unspecified;
    150     revision.kind=svn_opt_revision_head;
     213    revision.kind = ( svn_path_is_url(path.c_str()) ?
     214                      svn_opt_revision_head : svn_opt_revision_base );
    151215    apr_pool_t *subpool = svn_pool_create(pool_);
    152216    apr_array_header_t * properties;
     
    180244
    181245
    182   void SVN::client_log(std::string path, log_receiver_baton* lb)
    183   {
    184     // Allocate space in subpool to pool_ for apr_path (here a string).
    185     apr_pool_t *subpool = svn_pool_create(pool_);
    186     apr_array_header_t* apr_path=apr_array_make(subpool,1,4);
    187     // Copy path to apr_path.
    188     (*((const char **) apr_array_push(apr_path))) =
    189       apr_pstrdup(subpool, svn_path_internal_style(path.c_str(),subpool));
    190 
    191     // Setup to retrieve all commit logs.
    192     svn_opt_revision_t peg, start, head;
    193     peg.kind=svn_opt_revision_unspecified;
    194     start.kind=svn_opt_revision_number;
    195     start.value.number=0;
    196     head.kind=svn_opt_revision_head;
    197     svn_error_t* err=NULL;
    198     // Retrieving the last revision is only needed for the reserve
    199     // call below, not needed for the functionality here.
    200     if ((err=svn_ra_get_latest_revnum(ra_session_, &(head.value.number),
    201                                       subpool)))
    202       cleanup(err, subpool, "commit_dates: svn_ra_get_latest_revnum failed");
    203     // Acctually we do not know the size of vector (and reserve most
    204     // likely over-use memory), perhaps we should use lists instead,
    205     // or do we need the random access?
    206     lb->commit_dates.reserve(head.value.number+1); // revision 0 is also stored.
    207     lb->authors.reserve(head.value.number+1); // revision 0 is also stored.
    208     lb->rev.reserve(head.value.number+1); // revision 0 is also stored.
    209     if ((err=svn_client_log3(apr_path, &peg, &start, &head, 0, false, false,
    210                              log_message_receiver, static_cast<void*>(lb),
    211                              context_, subpool)))
    212       // cleanupp will throw an exception
    213       cleanup(err, subpool, "commit_dates: svn_client_log3 failed");
    214     svn_pool_destroy(subpool);
    215   }
    216 
    217 
    218   void SVN::cleanup(svn_error_t *err,apr_pool_t *pool,
    219                     const std::string& message)
    220   {
    221     svn_handle_error2(err,stderr,false,"svndigest: ");
    222     svn_error_clear(err);
    223     if (pool)
    224       svn_pool_destroy(pool);
    225     if (message.length()>0)
    226       throw SVNException(message);
    227   }
    228 
    229 
    230   void SVN::cleanup_failed_init(svn_error_t *err, const std::string& message)
    231   {
    232     cleanup(err,pool_);
    233     apr_allocator_destroy(allocator_);
    234     throw SVNException(message);
    235   }
    236 
    237 
    238   svn_error_t *
    239   SVN::log_message_receiver(void *baton, apr_hash_t *changed_paths,
    240                             svn_revnum_t rev, const char *author,
    241                             const char *date, const char *msg, apr_pool_t *pool)
    242   {
    243     struct log_receiver_baton *lb=static_cast<struct log_receiver_baton*>(baton);
    244     if (date && date[0])
    245       lb->commit_dates.push_back(date);
    246     else
    247       throw SVNException("No date defined for revision: " + rev);
    248     if (author && author[0])
    249       lb->authors.push_back(author);
    250     else
    251       lb->authors.push_back("");
    252     lb->rev.push_back(rev);
    253     if (msg)
    254       lb->msg.push_back(std::string(msg));
    255     else
    256       lb->msg.push_back(std::string(""));
    257     return SVN_NO_ERROR;
    258   }
    259 
    260 
    261   void SVN::setup_ra_session(const std::string& path) {
    262     // get a session to the repository
    263     if (svn_error_t *err=svn_client_open_ra_session(&ra_session_, path.c_str(),
    264                                                     context_,pool_))
    265       cleanup(err, NULL, "setup_ra_session: svn_client_open_ra_session failed");
    266   }
    267 
    268 
    269   void SVN::setup_wc_adm_access(const std::string& path)
    270   {
    271     // Set up svn administration area access. The whole structure is
    272     // setup, maybe this is unnecessary?
    273     const char* canonical_path=svn_path_internal_style(path.c_str(), pool_);
    274     if (svn_error_t *err=svn_wc_adm_open3(&adm_access_, NULL, canonical_path,
    275                                           false, -1, context_->cancel_func,
    276                                           context_->cancel_baton, pool_))
    277       cleanup(err, NULL, "setup_wc_adm_access: svn_wc_adm_open3 failed");
     246  SVN* SVN::instance(void)
     247  {
     248    if (!instance_)
     249      throw SVNException("SVN::instance(void): SVN singleton not initialized");
     250    return instance_;
     251  }
     252
     253
     254  SVN* SVN::instance(const std::string& url)
     255  {
     256    if (!instance_) {
     257      instance_=new SVN(url);
     258    }
     259    return instance_;
     260  }
     261
     262
     263  svn_error_t* SVN::root_url_receiver(void *baton, const char *,
     264                                      const svn_info_t *info, apr_pool_t*)
     265  {
     266    if (!info)
     267      throw SVNException(std::string("SVN::url_receriver: ") +
     268                         "Failed to acquire an svn info object");
     269
     270    root_url_receiver_baton* rurb=
     271      static_cast<struct root_url_receiver_baton*>(baton);
     272    if (info->repos_root_URL)
     273      rurb->path=info->repos_root_URL;
     274
     275    return SVN_NO_ERROR;
    278276  }
    279277
     
    299297  }
    300298
    301 
    302299}} // end of namespace svndigest and namespace theplu
Note: See TracChangeset for help on using the changeset viewer.