GME
13
|
00001 00023 #include "../StdAfx.h" 00024 00025 #if(USESVN) 00026 00027 #include ".\client.h" 00028 #include <crtdbg.h> // for ASSERT 00029 //#include <iostream> // remove this later 00030 #include "Pool.h" 00031 #include "Util.h" 00032 #include "svn_client.h" 00033 #include "svn_config.h" 00034 00035 extern std::string g_userName; 00036 extern std::string g_passWord; 00037 00038 Client::Client( const std::string& p_userName, const std::string& p_passWord) 00039 : m_notify2( 0) 00040 , m_prompter( 0) 00041 , m_commitMessageBuilder( 0) 00042 , m_userName( p_userName) 00043 , m_passWord( p_passWord) 00044 { 00045 Util::globalInit(); 00046 setPrompt( Prompter::makePrompter( new GPromptImpl())); 00047 // we set this: 00048 notification2( new ClientUtil::NotifyHelp()); 00049 m_ctx = NULL; 00050 m_ctxPool = std::auto_ptr<Pool>(new Pool()); 00051 } 00052 00053 Client::~Client(void) 00054 { 00055 if( m_prompter) delete m_prompter; 00056 m_prompter = 0; 00057 00058 // should we delete this also? 00059 if( m_commitMessageBuilder) delete m_commitMessageBuilder; 00060 m_commitMessageBuilder = 0; 00061 00062 notification2( 0); 00063 } 00064 00065 void Client::notification2( ClientUtil::NotifyHelp *notify2) 00066 { 00067 if( m_notify2) delete m_notify2; 00068 m_notify2 = notify2; 00069 } 00070 00071 void Client::setCommitMessageHandler( ClientUtil::CommitHelp::MsgBuilder* p_commitMessageBuilder) 00072 { 00073 if( m_commitMessageBuilder) delete m_commitMessageBuilder; 00074 m_commitMessageBuilder = p_commitMessageBuilder; 00075 } 00076 00077 00078 void Client::setPrompt( Prompter * p_prompter) 00079 { 00080 if( m_prompter) delete m_prompter; 00081 m_prompter = p_prompter; 00082 } 00083 00084 00085 // not so public interface: 00086 long Client::sub_checkout(const char *moduleName, const char *destPath, 00087 Revision &revision, Revision &pegRevision, 00088 bool recurse, bool ignoreExternals) 00089 { 00090 Pool reqPool; 00091 apr_pool_t * apr_pool = reqPool.pool(); 00092 00093 if(moduleName == NULL) 00094 { 00095 Util::throwNullPointerException("moduleName"); 00096 return -1; 00097 } 00098 if(destPath == NULL) 00099 { 00100 Util::throwNullPointerException("destPath"); 00101 return -1; 00102 } 00103 00104 Path url(moduleName, reqPool.pool()); 00105 Path path(destPath, reqPool.pool()); 00106 svn_error_t *Err = url.error_occured(); 00107 if(Err != NULL) 00108 { 00109 Util::handleSVNError(Err); 00110 return -1; 00111 } 00112 Err = path.error_occured(); 00113 if(Err != NULL) 00114 { 00115 Util::handleSVNError(Err); 00116 return -1; 00117 } 00118 svn_revnum_t retval; 00119 00120 svn_client_ctx_t *ctx = getContext(NULL, reqPool.pool()); 00121 if(ctx == NULL) 00122 { 00123 return -1; 00124 } 00125 00126 Err = svn_client_checkout2 (&retval, url.c_str(), 00127 path.c_str (), 00128 pegRevision.revision (), 00129 revision.revision (), 00130 recurse, 00131 ignoreExternals, 00132 ctx, 00133 apr_pool); 00134 00135 if(Err != NULL) 00136 { 00137 Util::handleSVNError(Err); 00138 return -1; 00139 } 00140 return retval; 00141 00142 } 00143 00144 long Client::sub_commit(Targets &targets, const char *message, bool recurse, 00145 bool noUnlock) 00146 { 00147 Pool reqPool; 00148 apr_pool_t * apr_pool = reqPool.pool(); 00149 svn_client_commit_info_t *commit_info = NULL; 00150 const apr_array_header_t *targets2 = targets.array(reqPool); 00151 svn_error_t *Err = targets.error_occured(); 00152 if(Err != NULL) 00153 { 00154 Util::handleSVNError(Err); 00155 return -1; 00156 } 00157 svn_client_ctx_t *ctx = getContext(message, apr_pool); 00158 if(ctx == NULL) 00159 { 00160 return -1; 00161 } 00162 Err = svn_client_commit2 (&commit_info, 00163 targets2, 00164 recurse, noUnlock, ctx, apr_pool); 00165 if(Err != NULL) 00166 Util::handleSVNError(Err); 00167 00168 if(commit_info && SVN_IS_VALID_REVNUM (commit_info->revision)) 00169 return commit_info->revision; 00170 00171 return -1; 00172 } 00173 00174 long Client::sub_commit3(Targets &targets, const char *message, bool recurse, 00175 bool noUnlock) 00176 { 00177 Pool reqPool; 00178 apr_pool_t * apr_pool = reqPool.pool(); 00179 svn_commit_info_t *commit3_info = NULL; 00180 const apr_array_header_t *targets2 = targets.array(reqPool); 00181 svn_error_t *Err = targets.error_occured(); 00182 if(Err != NULL) 00183 { 00184 Util::handleSVNError(Err); 00185 return -1; 00186 } 00187 svn_client_ctx_t *ctx = getContext(message, apr_pool); 00188 if(ctx == NULL) 00189 { 00190 return -1; 00191 } 00192 Err = svn_client_commit3(&commit3_info, 00193 targets2, 00194 recurse, noUnlock, ctx, apr_pool); 00195 if(Err != NULL) 00196 Util::handleSVNError(Err); 00197 00198 #if(0) 00199 typedef struct svn_commit_info_t 00200 { 00201 svn_revnum_t revision; 00202 const char *date; 00203 const char *author; 00204 const char *post_commit_err; 00205 } svn_commit_info_t; 00206 #endif 00207 00208 if(commit3_info && SVN_IS_VALID_REVNUM (commit3_info->revision)) 00209 return commit3_info->revision; 00210 00211 return -1; 00212 } 00213 00214 00215 bool Client::sub_update(Targets &targets, Revision &revision, bool recurse, 00216 bool ignoreExternals, std::vector< long>& res) 00217 { 00218 Pool reqPoolParent; 00219 // This function leaks if we don't use two pools 00220 Pool reqPool(reqPoolParent); 00221 apr_pool_t * apr_pool = reqPool.pool(); 00222 00223 svn_client_ctx_t *ctx = getContext(NULL, apr_pool); 00224 apr_array_header_t *retval; 00225 if(ctx == NULL) 00226 { 00227 return false; 00228 } 00229 const apr_array_header_t *array = targets.array(reqPool); 00230 svn_error_t *Err = targets.error_occured(); 00231 if(Err != NULL) 00232 { 00233 Util::handleSVNError(Err); 00234 return false; 00235 } 00236 00237 try 00238 { 00239 Err = svn_client_update2 (&retval, array, 00240 revision.revision (), 00241 recurse, 00242 ignoreExternals, 00243 ctx, 00244 apr_pool); 00245 } 00246 catch(...) 00247 { 00248 ASSERT(0); 00249 return false; 00250 } 00251 00252 if(Err != NULL) 00253 { 00254 Util::handleSVNError(Err); 00255 return false; 00256 } 00257 00258 res.resize( retval->nelts); 00259 for( int i = 0; i < retval->nelts; ++i) 00260 res[i] = APR_ARRAY_IDX (retval, i, svn_revnum_t); 00261 00262 return true; 00263 } 00264 00265 bool Client::sub_cleanup(const char *path) 00266 { 00267 Pool reqPool; 00268 apr_pool_t * apr_pool = reqPool.pool(); 00269 if(path == NULL) 00270 { 00271 Util::throwNullPointerException("path"); 00272 return false; 00273 } 00274 Path intPath(path, reqPool.pool()); 00275 svn_error_t *Err = intPath.error_occured(); 00276 if(Err != NULL) 00277 { 00278 Util::handleSVNError(Err); 00279 return false; 00280 } 00281 00282 svn_client_ctx_t *ctx = getContext(NULL, reqPool.pool()); 00283 if(ctx == NULL) 00284 { 00285 return false; 00286 } 00287 Err = svn_client_cleanup (intPath.c_str (), ctx, apr_pool); 00288 00289 if(Err != NULL) 00290 { 00291 Util::handleSVNError(Err); 00292 return false; 00293 } 00294 00295 return true; 00296 } 00297 00298 bool Client::sub_resolved(const char *path, bool recurse) 00299 { 00300 Pool reqPool; 00301 apr_pool_t * apr_pool = reqPool.pool(); 00302 if(path == NULL) 00303 { 00304 Util::throwNullPointerException("path"); 00305 return false; 00306 } 00307 Path intPath(path, reqPool.pool()); 00308 svn_error_t *Err = intPath.error_occured(); 00309 if(Err != NULL) 00310 { 00311 Util::handleSVNError(Err); 00312 return false; 00313 } 00314 svn_client_ctx_t *ctx = getContext(NULL, reqPool.pool()); 00315 if(ctx == NULL) 00316 { 00317 return false; 00318 } 00319 Err = svn_client_resolved (intPath.c_str (), 00320 recurse, 00321 ctx, 00322 apr_pool); 00323 00324 if(Err != NULL) 00325 { 00326 Util::handleSVNError(Err); 00327 return false; 00328 } 00329 00330 return true; 00331 } 00332 00333 00334 bool Client::sub_propertySet(const char *path, const char *name, 00335 const char *value, bool recurse, bool force) 00336 { 00337 Pool reqPool; 00338 if(path == NULL) 00339 { 00340 Util::throwNullPointerException("path"); 00341 return false; 00342 } 00343 if(name == NULL) 00344 { 00345 Util::throwNullPointerException("name"); 00346 return false; 00347 } 00348 if(value == NULL) 00349 { 00350 Util::throwNullPointerException("value"); 00351 return false; 00352 } 00353 svn_string_t *val = svn_string_create(value, reqPool.pool()); 00354 00355 00356 //propertySet(path, name, val->data, recurse, force); // modified from val to val->data 00357 //Path intPath(path, reqPool.pool()); 00358 svn_error_t *Err = NULL; // intPath.error_occured(); 00359 if(Err != NULL) 00360 { 00361 Util::handleSVNError(Err); 00362 return false; 00363 } 00364 00365 svn_client_ctx_t *ctx = getContext(NULL, reqPool.pool()); 00366 if(ctx == NULL) 00367 return false; 00368 Err = svn_client_propset2 (name, val, 00369 path, 00370 recurse, 00371 force, 00372 ctx, 00373 reqPool.pool()); 00374 if(Err!= NULL) 00375 { 00376 Util::handleSVNError(Err); // previously just handled the error and fall through to return true 00377 return false; 00378 } 00379 00380 return true; 00381 } 00382 00383 bool Client::sub_lock(Targets &targets, const char *comment, 00384 bool force) 00385 { 00386 Pool reqPool; 00387 const apr_array_header_t *targetsApr = targets.array(reqPool); 00388 svn_error_t *Err = targets.error_occured(); 00389 if(Err != NULL) 00390 { 00391 Util::handleSVNError(Err); 00392 return false; 00393 } 00394 apr_pool_t * apr_pool = reqPool.pool(); 00395 svn_client_ctx_t *ctx = getContext(NULL, reqPool.pool()); 00396 Err = svn_client_lock(targetsApr, comment, force, ctx, apr_pool); 00397 00398 if (Err != NULL) 00399 { 00400 Util::handleSVNError(Err); 00401 return false; 00402 } 00403 00404 return true; 00405 } 00406 00407 //svn_error_t * 00408 //svn_client_unlock(const apr_array_header_t *targets, 00409 // svn_boolean_t break_lock, 00410 // svn_client_ctx_t *ctx, 00411 // apr_pool_t *pool) 00412 00413 bool Client::sub_unlock(Targets &targets) 00414 { 00415 Pool reqPool; 00416 const apr_array_header_t *targetsApr = targets.array(reqPool); 00417 svn_error_t *Err = targets.error_occured(); 00418 if(Err != NULL) 00419 { 00420 Util::handleSVNError(Err); 00421 return false; 00422 } 00423 apr_pool_t * apr_pool = reqPool.pool(); 00424 svn_client_ctx_t *ctx = getContext(NULL, reqPool.pool()); 00425 Err = svn_client_unlock(targetsApr, true, ctx, apr_pool); 00426 00427 if (Err != NULL) 00428 { 00429 Util::handleSVNError(Err); 00430 return false; 00431 } 00432 00433 return true; 00434 } 00435 00436 00437 ClientUtil::StatusInfo Client::sub_single_status(const char *path, bool onServer) 00438 { 00439 ClientUtil::StatusInfo null_pair; 00440 ClientUtil::StatusHelp::StatusBaton statusBaton; 00441 Pool reqPool; 00442 svn_revnum_t youngest = SVN_INVALID_REVNUM; 00443 svn_opt_revision_t rev; 00444 00445 if(path == NULL) 00446 { 00447 Util::throwNullPointerException("path"); 00448 return null_pair; 00449 } 00450 00451 svn_client_ctx_t *ctx = getContext(NULL, reqPool.pool()); 00452 if(ctx == NULL) 00453 { 00454 return null_pair; 00455 } 00456 00457 00458 rev.kind = svn_opt_revision_unspecified; 00459 statusBaton.m_pool = reqPool.pool(); 00460 Path intPath(path, reqPool.pool()); 00461 svn_error_t *Err = intPath.error_occured(); 00462 if(Err != NULL) 00463 { 00464 Util::handleSVNError(Err); 00465 return null_pair; 00466 } 00467 00468 Err = svn_client_status2 (&youngest, intPath.c_str(), &rev, 00469 ClientUtil::StatusHelp::statusReceiver, // callback of type svn_wc_status_func2_t 00470 &statusBaton, // callback's parameter 00471 FALSE, // DESCEND 00472 TRUE, // get_All 00473 onServer ? TRUE : FALSE, //update 00474 FALSE, // no_ignore, 00475 FALSE, // ignore externals 00476 ctx, 00477 reqPool.pool()); 00478 00479 if(Err == NULL) 00480 { 00481 int size = (int) statusBaton.m_statusVect.size(); 00482 if (size == 0) 00483 return null_pair; 00484 00485 // when svn_client_status is used with a directory, the status of the 00486 // directory itself and the status of all its direct children are 00487 // returned 00488 // we just want the status of the directory (ie the status of the 00489 // element with the shortest path) 00490 int j = 0; 00491 for (int i = 0; i < size; i++) 00492 { 00493 if (strlen(statusBaton.m_statusVect[i].m_path) < 00494 strlen(statusBaton.m_statusVect[j].m_path)) 00495 j = i; 00496 } 00497 00498 null_pair.first = statusBaton.m_statusVect[j].m_path; 00499 null_pair.second = (statusBaton.m_statusVect[j].m_status)? 1:0; 00500 00501 //typedef struct svn_wc_status2_t 00502 //{ 00503 // svn_wc_entry_t *entry; 00504 // enum svn_wc_status_kind text_status; 00505 // enum svn_wc_status_kind prop_status; 00506 // svn_boolean_t locked; 00507 // svn_boolean_t copied; 00508 // svn_boolean_t switched; 00509 // enum svn_wc_status_kind repos_text_status; 00510 // enum svn_wc_status_kind repos_prop_status; 00511 // svn_lock_t *repos_lock; 00512 // const char *url; 00513 // svn_revnum_t ood_last_cmt_rev; 00514 // apr_time_t ood_last_cmt_date; 00515 // svn_node_kind_t ood_kind; 00516 // const char *ood_last_cmt_author; 00517 //} svn_wc_status2_t; 00518 00519 return null_pair; 00520 } 00521 else 00522 { 00523 Util::handleSVNError(Err); 00524 return null_pair; 00525 } 00526 } 00527 00528 // locked status not reported correctly 00529 // use info instead 00530 ClientUtil::StatusExtInfoVec Client::sub_extended_status( const char *p_path, bool p_onServer) 00531 { 00532 ClientUtil::StatusExtInfoVec res; 00533 ClientUtil::StatusHelp::StatusBaton statusBaton; 00534 Pool reqPool; 00535 svn_revnum_t youngest = SVN_INVALID_REVNUM; 00536 svn_opt_revision_t rev; 00537 00538 if(p_path == NULL) 00539 { 00540 Util::throwNullPointerException("p_path"); 00541 return res; 00542 } 00543 00544 svn_client_ctx_t *ctx = getContext(NULL, reqPool.pool()); 00545 if(ctx == NULL) 00546 { 00547 return res; 00548 } 00549 00550 00551 rev.kind = svn_opt_revision_unspecified; 00552 statusBaton.m_pool = reqPool.pool(); 00553 Path intPath(p_path, reqPool.pool()); 00554 svn_error_t *Err = intPath.error_occured(); 00555 if(Err != NULL) 00556 { 00557 Util::handleSVNError(Err); 00558 return res; 00559 } 00560 00561 Err = svn_client_status2 (&youngest, intPath.c_str(), &rev, 00562 ClientUtil::StatusHelp::statusReceiver, // callback of type svn_wc_status_func2_t 00563 &statusBaton, // callback's parameter 00564 FALSE, // DESCEND 00565 TRUE, // get_All 00566 p_onServer ? TRUE : FALSE, //update 00567 FALSE, // no_ignore, 00568 FALSE, // ignore externals 00569 ctx, 00570 reqPool.pool()); 00571 00572 if(Err == NULL) 00573 { 00574 int size = (int) statusBaton.m_statusVect.size(); 00575 if (size == 0) 00576 return res; 00577 00578 // when svn_client_status is used with a directory, the status of the 00579 // directory itself and the status of all its direct children are 00580 // returned 00581 // we just want the status of the directory (ie the status of the 00582 // element with the shortest path) 00583 int j = 0; 00584 for (int i = 0; i < size; i++) 00585 { 00586 //if( statusBaton.m_statusVect[i].m_status->locked) 00587 // std::cout << "Stat " << "Locked" << std::endl; 00588 //else 00589 // std::cout << "Stat " << "NotLocked" << std::endl; 00590 ClientUtil::StatusExtInfo r = statusBaton.m_statusVect[i]; 00591 res.push_back( r); 00592 } 00593 00594 //typedef struct svn_wc_status2_t 00595 //{ 00596 // svn_wc_entry_t *entry; 00597 // enum svn_wc_status_kind text_status; 00598 // enum svn_wc_status_kind prop_status; 00599 // svn_boolean_t locked; 00600 // svn_boolean_t copied; 00601 // svn_boolean_t switched; 00602 // enum svn_wc_status_kind repos_text_status; 00603 // enum svn_wc_status_kind repos_prop_status; 00604 // svn_lock_t *repos_lock; 00605 // const char *url; 00606 // svn_revnum_t ood_last_cmt_rev; 00607 // apr_time_t ood_last_cmt_date; 00608 // svn_node_kind_t ood_kind; 00609 // const char *ood_last_cmt_author; 00610 //} svn_wc_status2_t; 00611 00612 return res; 00613 } 00614 else 00615 { 00616 Util::handleSVNError(Err); 00617 return res; 00618 } 00619 } 00620 00621 00622 svn_client_ctx_t * Client::getContext(const char *p_strMessage, apr_pool_t *pool) 00623 { 00624 if (m_ctx == NULL) 00625 { 00626 m_ctx = createContext(NULL, m_ctxPool->pool()); 00627 } 00628 m_commitMessage = p_strMessage ? p_strMessage : "Empty"; 00629 ((ClientUtil::CommitHelp::LogMsgBaton*)m_ctx->log_msg_baton2)->m_message = m_commitMessage.c_str(); 00630 return m_ctx; 00631 } 00632 00633 svn_client_ctx_t * Client::createContext(const char *p_strMessage, apr_pool_t *pool) 00634 { 00635 svn_auth_baton_t *ab; 00636 svn_client_ctx_t *ctx; 00637 svn_error_t *err = NULL; 00638 if (( err = svn_client_create_context(&ctx, pool))) 00639 { 00640 Util::handleSVNError(err); 00641 return NULL; 00642 } 00643 00644 apr_array_header_t *providers 00645 = apr_array_make (pool, 10, sizeof (svn_auth_provider_object_t *)); 00646 00647 /* The main disk-caching auth providers, for both 00648 'username/password' creds and 'username' creds. */ 00649 svn_auth_provider_object_t *provider; // provider->vtable->save_credentials is a function pointer to saving to the cache 00650 #ifdef WIN32 00651 svn_client_get_windows_simple_provider (&provider, pool); 00652 APR_ARRAY_PUSH (providers, svn_auth_provider_object_t *) = provider; 00653 #endif 00654 svn_client_get_simple_provider (&provider, pool); 00655 APR_ARRAY_PUSH (providers, svn_auth_provider_object_t *) = provider; 00656 svn_client_get_username_provider (&provider, pool); 00657 APR_ARRAY_PUSH (providers, svn_auth_provider_object_t *) = provider; 00658 00659 /* The server-cert, client-cert, and client-cert-password providers. */ 00660 svn_client_get_ssl_server_trust_file_provider (&provider, pool); 00661 APR_ARRAY_PUSH (providers, svn_auth_provider_object_t *) = provider; 00662 svn_client_get_ssl_client_cert_file_provider (&provider, pool); 00663 APR_ARRAY_PUSH (providers, svn_auth_provider_object_t *) = provider; 00664 svn_client_get_ssl_client_cert_pw_file_provider (&provider, pool); 00665 APR_ARRAY_PUSH (providers, svn_auth_provider_object_t *) = provider; 00666 00667 if(m_prompter != NULL) 00668 { 00669 /* Two basic prompt providers: username/password, and just username.*/ 00670 provider = m_prompter->getProviderSimple(pool); 00671 APR_ARRAY_PUSH (providers, svn_auth_provider_object_t *) = provider; 00672 00673 provider = m_prompter->getProviderUsername(pool); 00674 APR_ARRAY_PUSH (providers, svn_auth_provider_object_t *) = provider; 00675 00676 /* Three ssl prompt providers, for server-certs, client-certs, 00677 and client-cert-passphrases. */ 00678 provider = m_prompter->getProviderServerSSLTrust(pool); 00679 APR_ARRAY_PUSH (providers, svn_auth_provider_object_t *) = provider; 00680 00681 provider = m_prompter->getProviderClientSSL(pool); 00682 APR_ARRAY_PUSH (providers, svn_auth_provider_object_t *) = provider; 00683 00684 provider = m_prompter->getProviderClientSSLPassword(pool); 00685 APR_ARRAY_PUSH (providers, svn_auth_provider_object_t *) = provider; 00686 } 00687 00688 00689 00690 /* Build an authentication baton to give to libsvn_client. */ 00691 svn_auth_open (&ab, providers, pool); 00692 00693 /* Place any default --username or --password credentials into the 00694 auth_baton's run-time parameter hash. ### Same with --no-auth-cache? */ 00695 if (!m_userName.empty()) 00696 svn_auth_set_parameter(ab, SVN_AUTH_PARAM_DEFAULT_USERNAME, m_userName.c_str()); 00697 else if( !g_userName.empty()) // g_userName is NOT empty => g_userName != m_userName 00698 svn_auth_set_parameter(ab, SVN_AUTH_PARAM_DEFAULT_USERNAME, g_userName.c_str()); // this might have been filled by prompt() 00699 00700 if (!m_passWord.empty()) 00701 svn_auth_set_parameter(ab, SVN_AUTH_PARAM_DEFAULT_PASSWORD, m_passWord.c_str()); 00702 else if( !g_passWord.empty()) // g_passWord is NOT empty => g_passWord != m_passWord 00703 svn_auth_set_parameter(ab, SVN_AUTH_PARAM_DEFAULT_PASSWORD, g_passWord.c_str()); // this might have been filled by prompt() 00704 00705 //svn_auth_set_parameter(ab, SVN_AUTH_CRED_SSL_CLIENT_CERT, 00706 00707 ctx->auth_baton = ab; 00708 00709 ctx->notify_func = 0;//Notify::notify; 00710 ctx->notify_baton = 0;//m_notify; 00711 00712 ctx->notify_func2 = ClientUtil::NotifyHelp::notify2; 00713 ctx->notify_baton2 = m_notify2; 00714 00715 // a callback to be used to see if we (the client) wish to cancel the running operation 00716 // client's cancelOperation() public method allows users to ask for cancel 00717 00718 ctx->cancel_func = ClientUtil::OtherHelp::checkCancel; 00719 ctx->cancel_baton = this; 00720 00721 m_cancelOperation = false; 00722 00723 // 1.2 logic with log_msg 00724 //ctx->log_msg_func = getCommitMessage; // used by commit 00725 //ctx->log_msg_baton = getCommitMessageBaton(message); // ditto 00726 00727 // 1.3 logic? 00728 // if not filled (is NULL) means that Subversion should try log_msg_func 00729 ctx->log_msg_baton2 = ClientUtil::CommitHelp::createLogMsgBaton(p_strMessage, m_commitMessageBuilder, pool); 00730 ctx->log_msg_func2 = ClientUtil::CommitHelp::logMsg; 00731 00732 ctx->log_msg_baton = 0; // safety 1st 00733 ctx->log_msg_func = 0; 00734 00735 const char *configDir = m_configDir.c_str(); 00736 if(m_configDir.length() == 0) 00737 configDir = NULL; 00738 if (( err = 00739 svn_config_get_config (&(ctx->config), configDir, pool))) 00740 { 00741 Util::handleSVNError(err); 00742 return NULL; 00743 } 00744 00745 // no progress feedback yet 00746 ctx->progress_func = 0; 00747 ctx->progress_baton = 0; 00748 00749 00750 // Use custom ssh client "GMEplink" (no console window) 00751 CString appPath; 00752 ::GetModuleFileName(NULL, appPath.GetBuffer(MAX_PATH), MAX_PATH); 00753 appPath.ReleaseBuffer(); 00754 appPath = appPath.Left(appPath.ReverseFind('\\')+1); 00755 svn_config_t * cfg = (svn_config_t *)apr_hash_get (ctx->config, SVN_CONFIG_CATEGORY_CONFIG, 00756 APR_HASH_KEY_STRING); 00757 const char * sshValue = NULL; 00758 svn_config_get(cfg, &sshValue, SVN_CONFIG_SECTION_TUNNELS, "ssh", ""); 00759 if ((sshValue == NULL)||(sshValue[0] == 0)) { 00760 CString tsvn_ssh = _T("\"") + appPath + _T("GMEplink.exe") + _T("\""); 00761 tsvn_ssh.Replace('\\', '/'); 00762 svn_config_set(cfg, SVN_CONFIG_SECTION_TUNNELS, "ssh", tsvn_ssh); 00763 } 00764 00765 svn_config_set(cfg, SVN_CONFIG_SECTION_MISCELLANY, SVN_CONFIG_OPTION_ENABLE_AUTO_PROPS, false); 00766 00767 return ctx; 00768 } 00769 00770 void ClientUtil::CommitHelp::MsgBuilder::dealWithItem( std::string& res, svn_client_commit_item_t * item) 00771 { 00772 //const char * item->path 00773 //svn_node_kind_t item->kind; 00774 //const char * item->url; 00775 //const char * item->copyfrom_url; 00776 //svn_revnum_t item->revision; 00777 if( !item) 00778 { 00779 res += "<Null item>\n"; 00780 return; 00781 } 00782 00783 if(item->state_flags & SVN_CLIENT_COMMIT_ITEM_ADD) 00784 res += "[Add]"; 00785 if(item->state_flags & SVN_CLIENT_COMMIT_ITEM_DELETE) 00786 res += "[Del]"; 00787 if(item->state_flags & SVN_CLIENT_COMMIT_ITEM_TEXT_MODS) 00788 res += "[Mod]"; 00789 if(item->state_flags & SVN_CLIENT_COMMIT_ITEM_PROP_MODS) 00790 res += "[Pro]"; 00791 if(item->state_flags & SVN_CLIENT_COMMIT_ITEM_IS_COPY) 00792 { 00793 res += "[Cop]"; 00794 res += "From: "; res += ClientUtil::charstar2str( item->copyfrom_url, "CopyFromURL"); 00795 } 00796 00797 char buff[32]; itoa( item->revision, &buff[0], 10); 00798 res += " Rev#"; res += buff; 00799 res += " "; 00800 res += ClientUtil::charstar2str( item->path, "Path"); 00801 res += "\n"; 00802 } 00803 00804 std::string ClientUtil::CommitHelp::MsgBuilder::build(const apr_array_header_t *commit_items) 00805 { 00806 std::string m; 00807 if( !commit_items) return m; 00808 00809 int count = commit_items->nelts; 00810 for(int i = 0; i < count; i++) 00811 { 00812 // get the commit item 00813 svn_client_commit_item_t *item 00814 = ((svn_client_commit_item_t **) commit_items->elts)[i]; 00815 00816 dealWithItem( m, item); 00817 } 00818 00819 return m; 00820 } 00821 00843 // static, callback method 00844 svn_error_t * ClientUtil::CommitHelp::logMsg(const char **log_msg, 00845 const char **tmp_file, 00846 const apr_array_header_t *commit_items, 00847 void *baton, 00848 apr_pool_t *pool) 00849 { 00850 *log_msg = NULL; 00851 *tmp_file = NULL; 00852 LogMsgBaton *lmb = (LogMsgBaton *) baton; // convert the baton to the specific structure we passed in 00853 00854 // is there a message composer? 00855 if (lmb && lmb->m_messageHandler) 00856 { 00857 // build special message based on the to-be-commited-items array 00858 std::string spec_msg = lmb->m_messageHandler->build( commit_items); 00859 *log_msg = apr_pstrdup( pool, spec_msg.c_str()); 00860 return SVN_NO_ERROR; 00861 } 00862 else if (lmb && lmb->m_message) // or at least a message? 00863 { 00864 *log_msg = apr_pstrdup (pool, lmb->m_message); 00865 return SVN_NO_ERROR; 00866 } 00867 00868 return SVN_NO_ERROR; 00869 } 00870 00871 // static 00872 void * ClientUtil::CommitHelp::createLogMsgBaton( const char * p_strMessage, CommitHelp::MsgBuilder * p_msgComposer, apr_pool_t *pool) 00873 { 00874 // the baton created by this method will affect 00875 // how CommitHelp::logMsg() will deal with the 00876 // array of commit_items 00877 00878 if( p_strMessage != NULL || p_msgComposer) 00879 { 00880 LogMsgBaton *baton = (LogMsgBaton *) apr_palloc (pool, sizeof (*baton)); 00881 00882 baton->m_message = p_strMessage; // beware: ptr assignment only !! 00883 baton->m_messageHandler = p_msgComposer; 00884 00885 return baton; 00886 } 00887 //return NULL; 00888 00889 // create a baton with dummy string value for empty p_strMessages as well: 00890 static const char * def_str = "Default"; 00891 LogMsgBaton *baton = (LogMsgBaton *) apr_palloc (pool, sizeof (*baton)); 00892 baton->m_message = def_str; // beware: ptr assignment only !! 00893 return baton; 00894 } 00895 00896 void Client::cancelOperation() 00897 { 00898 m_cancelOperation = true; 00899 } 00900 00901 // static, callback method 00902 svn_error_t * ClientUtil::OtherHelp::checkCancel(void *cancelBaton) 00903 { 00904 Client *that = (Client*)cancelBaton; 00905 if(that->m_cancelOperation) 00906 return svn_error_create (SVN_ERR_CANCELLED, NULL, 00907 "Operation canceled"); 00908 else 00909 return SVN_NO_ERROR; 00910 } 00911 00912 // static, callback method, conforms to svn_wc_status_func2_t 00913 void ClientUtil::StatusHelp::statusReceiver( void *baton, const char *path, 00914 svn_wc_status2_t *status) 00915 { 00916 StatusBaton *status_baton = (StatusBaton*) baton; 00917 StatusEntry status_entry; 00918 status_entry.m_path = apr_pstrdup( status_baton->m_pool, path); 00919 status_entry.m_status = svn_wc_dup_status2( status, status_baton->m_pool); 00920 status_baton->m_statusVect.push_back( status_entry); 00921 } 00922 00930 void ClientUtil::NotifyHelp::notify2( void *baton, 00931 const svn_wc_notify_t *notify, 00932 apr_pool_t *pool) 00933 { 00934 // Notify the world that @a notify->action has happened to @a notify->path. 00935 00936 // a NotifyHelp object is used as the baton 00937 NotifyHelp * that = (NotifyHelp *) baton; 00938 if( that) // sanity check 00939 { 00940 // call our method 00941 that->onNotify( notify, pool); 00942 } 00943 } 00944 00945 // we deal with the notification that the @a notify->action has happened to @a notify->path. 00946 void ClientUtil::NotifyHelp::onNotify( const svn_wc_notify_t *notify, apr_pool_t *pool) 00947 { 00948 if (notify->action == svn_wc_notify_failed_lock) { 00949 char errbuff[BUFSIZ]; 00950 const char* errbuff2 = svn_err_best_message(notify->err, errbuff, BUFSIZ); 00951 m_msg.append(errbuff2 ? errbuff2 : errbuff); 00952 m_msg.append("<br>"); // This is a terrible hack 00953 m_OK = false; 00954 } 00955 } 00956 00957 // 00958 bool Client::info2Qck( const char* p_path, bool p_recurse, ClientUtil::InfoHelp::InfoVec& p_infoVect, bool p_suppressErrorMsg) 00959 { 00960 return sub_info2( p_path, Revision(), Revision(), p_recurse, p_infoVect, p_suppressErrorMsg); 00961 } 00962 00963 bool Client::sub_info2(const char *path, Revision &revision, Revision &pegRevision, bool recurse, ClientUtil::InfoHelp::InfoVec& p_infoVect, bool p_suppressIllegalUrlErrorMsg) 00964 { 00965 ClientUtil::InfoHelp::InfoBaton info_baton; 00966 Pool reqPool; 00967 00968 if(path == NULL) 00969 { 00970 Util::throwNullPointerException("path"); 00971 return false; 00972 } 00973 00974 svn_client_ctx_t *ctx = getContext(NULL, reqPool.pool()); 00975 if(ctx == NULL) 00976 { 00977 return false; 00978 } 00979 Path checkedPath(path, reqPool.pool()); 00980 svn_error_t *Err = checkedPath.error_occured(); 00981 if(Err != NULL) 00982 { 00983 Util::handleSVNError(Err); 00984 return false; 00985 } 00986 00987 info_baton.m_pool = reqPool.pool(); 00988 00989 Err = svn_client_info ( 00990 checkedPath.c_str(), 00991 pegRevision.revision(), 00992 revision.revision(), 00993 ClientUtil::InfoHelp::infoReceiver, // callback function 00994 &info_baton, // callback function's input baton parameter 00995 recurse ? TRUE :FALSE, 00996 ctx, 00997 reqPool.pool()); 00998 00999 if (Err == NULL) 01000 { 01001 p_infoVect = info_baton.m_infoVect; // copy the vector, could also use apr specific copier? 01002 return true; 01003 } 01004 else 01005 { 01006 // suppress SVN_ERR_RA_ILLEGAL_URL and SVN_ERR_ENTRY_MISSING_URL only, if allowed by p_suppressIllegalUrlErrorMsg 01007 if( !p_suppressIllegalUrlErrorMsg || 01008 p_suppressIllegalUrlErrorMsg && Err->apr_err != SVN_ERR_RA_ILLEGAL_URL && Err->apr_err != SVN_ERR_ENTRY_MISSING_URL) 01009 Util::handleSVNError(Err); 01010 return false; 01011 } 01012 } 01013 01014 // static, callback method 01015 svn_error_t *ClientUtil::InfoHelp::infoReceiver(void *baton, 01016 const char *path, 01017 const svn_info_t *info, 01018 apr_pool_t *pool) 01019 { 01020 // we don't create here java Status object as we don't want too many local 01021 // references 01022 InfoBaton *info_baton = (InfoBaton*) baton; // convert the baton to the specific structure we passed in 01023 InfoEntry info_entry; 01024 info_entry.m_path = apr_pstrdup( info_baton->m_pool, path); 01025 info_entry.m_info = (svn_info_t*) apr_pcalloc ( info_baton->m_pool, sizeof(svn_info_t)); 01026 info_entry.m_info->URL = apr_pstrdup( info_baton->m_pool,info->URL); 01027 info_entry.m_info->rev = info->rev; 01028 info_entry.m_info->kind = info->kind; 01029 info_entry.m_info->repos_root_URL = apr_pstrdup(info_baton->m_pool, 01030 info->repos_root_URL); 01031 info_entry.m_info->repos_UUID = apr_pstrdup( info_baton->m_pool, info->repos_UUID); 01032 info_entry.m_info->last_changed_rev = info->last_changed_rev; 01033 info_entry.m_info->last_changed_date = info->last_changed_date; 01034 info_entry.m_info->last_changed_author = apr_pstrdup(info_baton->m_pool, 01035 info->last_changed_author); 01036 if(info->lock != NULL) 01037 info_entry.m_info->lock = svn_lock_dup( info->lock, info_baton->m_pool); 01038 else 01039 info_entry.m_info->lock = NULL; 01040 info_entry.m_info->has_wc_info = info->has_wc_info; 01041 info_entry.m_info->schedule = info->schedule; 01042 info_entry.m_info->copyfrom_url = apr_pstrdup( info_baton->m_pool, 01043 info->copyfrom_url); 01044 info_entry.m_info->copyfrom_rev = info->copyfrom_rev; 01045 info_entry.m_info->text_time = info->text_time; 01046 info_entry.m_info->prop_time = info->prop_time; 01047 info_entry.m_info->checksum = apr_pstrdup( info_baton->m_pool, info->checksum); 01048 info_entry.m_info->conflict_old = apr_pstrdup( info_baton->m_pool, 01049 info->conflict_old); 01050 info_entry.m_info->conflict_new = apr_pstrdup( info_baton->m_pool, 01051 info->conflict_new); 01052 info_entry.m_info->conflict_wrk = apr_pstrdup( info_baton->m_pool, 01053 info->conflict_wrk); 01054 info_entry.m_info->prejfile = apr_pstrdup( info_baton->m_pool, info->prejfile); 01055 01056 info_baton->m_infoVect.push_back( info_entry); 01057 return SVN_NO_ERROR; 01058 } 01059 01060 int Client::sub_add( const char *p_pathOrUrl, bool p_rec) 01061 { 01062 Pool reqPool; 01063 apr_pool_t * apr_pool = reqPool.pool(); 01064 01065 if(p_pathOrUrl == NULL) 01066 { 01067 Util::throwNullPointerException("p_pathOrUrl"); 01068 return -1; 01069 } 01070 01071 Path url(p_pathOrUrl, reqPool.pool()); 01072 01073 svn_error_t *Err = url.error_occured(); 01074 if(Err != NULL) 01075 { 01076 Util::handleSVNError(Err); 01077 return -1; 01078 } 01079 01080 svn_client_ctx_t *ctx = getContext(NULL, reqPool.pool()); 01081 if(ctx == NULL) 01082 { 01083 return -1; 01084 } 01085 01086 Err = svn_client_add3 ( url.c_str(), 01087 p_rec, // recursive 01088 true, //force 01089 true, // no ignore 01090 ctx, 01091 apr_pool); 01092 01093 if(Err != NULL) 01094 { 01095 Util::handleSVNError(Err); 01096 return -1; 01097 } 01098 return 1; 01099 } 01100 01101 01102 long Client::sub_mkdir(Targets &targets, const char * p_msg) 01103 { 01104 Pool reqPool; 01105 apr_pool_t * apr_pool = reqPool.pool(); 01106 svn_client_commit_info_t *commit_info = NULL; 01107 // 01108 // svn_client_mkdir takes svn_client_commit_info_t 01109 // svn_client_mkdir2 takes svn_commit_info_t 01110 // 01111 const apr_array_header_t *targets2 = targets.array(reqPool); 01112 svn_error_t *Err = targets.error_occured(); 01113 if(Err != NULL) 01114 { 01115 Util::handleSVNError(Err); 01116 return -1; 01117 } 01118 svn_client_ctx_t *ctx = getContext(p_msg, reqPool.pool()); 01119 if(ctx == NULL) 01120 { 01121 return -1; 01122 } 01123 01124 Err = svn_client_mkdir( &commit_info, 01125 targets2, // paths 01126 ctx, 01127 apr_pool); 01128 01129 if(Err != NULL) 01130 Util::handleSVNError(Err); 01131 01132 if(commit_info && SVN_IS_VALID_REVNUM (commit_info->revision)) 01133 return commit_info->revision; 01134 01135 return -1; 01136 } 01137 01138 long Client::sub_mkdir2( Targets& targets, const char * p_msg) 01139 { 01140 Pool reqPool; 01141 apr_pool_t * apr_pool = reqPool.pool(); 01142 svn_commit_info_t *commit2_info = NULL; 01143 01144 const apr_array_header_t *targets2 = targets.array(reqPool); 01145 svn_error_t *Err = targets.error_occured(); 01146 if(Err != NULL) 01147 { 01148 Util::handleSVNError(Err); 01149 return -1; 01150 } 01151 svn_client_ctx_t *ctx = getContext(p_msg, reqPool.pool()); 01152 if(ctx == NULL) 01153 { 01154 return -1; 01155 } 01156 01157 Err = svn_client_mkdir2( &commit2_info, 01158 targets2, // paths 01159 ctx, 01160 apr_pool); 01161 01162 if(Err != NULL) 01163 Util::handleSVNError(Err); 01164 01165 if( commit2_info && SVN_IS_VALID_REVNUM (commit2_info->revision)) 01166 return commit2_info->revision; 01167 01168 return -1; 01169 } 01170 01171 // 01172 // std::string.append( const char * ) crashes if parameter ptr is 0, that's why this function is useful 01173 // 01174 // static 01175 std::string ClientUtil::charstar2str( const char* p_charStar, const std::string p_name) 01176 { 01177 if( p_charStar) 01178 { 01179 return std::string( p_charStar); 01180 } 01181 01182 return std::string( "<no" + p_name + ">"); 01183 } 01184 01185 #endif