1 // 2 // ==================================================================== 3 // (c) 2003-2019 Barry A Scott. All rights reserved. 4 // 5 // This software is licensed as described in the file LICENSE.txt, 6 // which you should have received as part of this distribution. 7 // 8 // ==================================================================== 9 // 10 #ifndef __PYSVN_SVNENV__ 11 #define __PYSVN_SVNENV__ 12 13 #include "CXX/Objects.hxx" 14 15 #if !defined( PYCXX_MAKEVERSION ) || PYCXX_VERSION < PYCXX_MAKEVERSION( 6, 2, 4 ) 16 #error PyCXX version 6.2.4 or later required 17 #endif 18 19 #include <svn_version.h> 20 #include <svn_client.h> 21 #include <svn_dirent_uri.h> 22 #include <svn_path.h> 23 #include <svn_props.h> 24 #include <svn_fs.h> 25 #include <svn_repos.h> 26 #include <apr_xlate.h> 27 28 #include <string> 29 30 #if !defined( SVN_VER_MAJOR ) 31 #error "SVN_VER_MAJOR not defined" 32 #endif 33 34 #if !defined( SVN_VER_MINOR ) 35 #error "SVN_VER_MINOR not defined" 36 #endif 37 38 // SVN 1.1 or later 39 #if (SVN_VER_MAJOR == 1 && SVN_VER_MINOR >= 1) || SVN_VER_MAJOR > 1 40 #define PYSVN_HAS_CLIENT_ADD2 41 #define PYSVN_HAS_CLIENT_DIFF_PEG 42 #define PYSVN_HAS_CLIENT_EXPORT2 43 #define PYSVN_HAS_CLIENT_MERGE_PEG 44 #define PYSVN_HAS_CLIENT_VERSION 45 #endif 46 47 // SVN 1.2 or later 48 #if (SVN_VER_MAJOR == 1 && SVN_VER_MINOR >= 2) || SVN_VER_MAJOR > 1 49 #define PYSVN_HAS_CLIENT_ANNOTATE2 50 #define PYSVN_HAS_CLIENT_CAT2 51 #define PYSVN_HAS_CLIENT_CHECKOUT2 52 #define PYSVN_HAS_CLIENT_COMMIT2 53 #define PYSVN_HAS_CLIENT_DIFF_PEG2 54 #define PYSVN_HAS_CLIENT_DIFF2 55 #define PYSVN_HAS_CLIENT_EXPORT3 56 #define PYSVN_HAS_CLIENT_INFO 57 #define PYSVN_HAS_CLIENT_LOCK 58 #define PYSVN_HAS_CLIENT_LOG2 59 #define PYSVN_HAS_CLIENT_LS2 60 #define PYSVN_HAS_CLIENT_MOVE2 61 #define PYSVN_HAS_CLIENT_PROPGET2 62 #define PYSVN_HAS_CLIENT_PROPLIST2 63 #define PYSVN_HAS_CLIENT_PROPSET2 64 #define PYSVN_HAS_CLIENT_STATUS2 65 #define PYSVN_HAS_CLIENT_UPDATE2 66 #define PYSVN_HAS_CONTEXT_NOTIFY2 67 #define PYSVN_HAS_WC_ADM_PROBE_OPEN3 68 #endif 69 70 // SVN 1.3 or later 71 #if (SVN_VER_MAJOR == 1 && SVN_VER_MINOR >= 3) || SVN_VER_MAJOR > 1 72 #define PYSVN_HAS_SVN_CLIENT_COMMIT_ITEM2_T 73 #define PYSVN_HAS_SVN_COMMIT_INFO_T 74 #define PYSVN_HAS_CONTEXT_LOG_MSG2 75 #define PYSVN_HAS_CONTEXT_PROGRESS 76 77 #define PYSVN_HAS_WC_ADM_DIR 78 79 #define PYSVN_HAS_CLIENT_ADD3 80 #define PYSVN_HAS_CLIENT_COMMIT3 81 #define PYSVN_HAS_CLIENT_COPY2 82 #define PYSVN_HAS_CLIENT_DELETE2 83 #define PYSVN_HAS_CLIENT_DIFF_PEG3 84 #define PYSVN_HAS_CLIENT_DIFF3 85 #define PYSVN_HAS_CLIENT_IMPORT2 86 #define PYSVN_HAS_CLIENT_LS3 87 #define PYSVN_HAS_CLIENT_MKDIR2 88 #define PYSVN_HAS_CLIENT_MOVE3 89 #endif 90 91 // SVN 1.4 or later 92 #if (SVN_VER_MAJOR == 1 && SVN_VER_MINOR >= 4) || SVN_VER_MAJOR > 1 93 #define PYSVN_HAS_CLIENT_ANNOTATE3 94 #define PYSVN_HAS_CLIENT_COPY3 95 #define PYSVN_HAS_CLIENT_DIFF_SUMMARIZE 96 #define PYSVN_HAS_CLIENT_LIST 97 #define PYSVN_HAS_CLIENT_LOG3 98 #define PYSVN_HAS_CLIENT_MERGE2 99 #define PYSVN_HAS_CLIENT_MERGE_PEG2 100 #define PYSVN_HAS_CLIENT_MOVE4 101 #define PYSVN_HAS_DIFF_FILE_IGNORE_SPACE 102 #define PYSVN_HAS_SVN_AUTH_PROVIDERS 103 #define PYSVN_HAS_IO_OPEN_UNIQUE_FILE2 104 #endif 105 106 // SVN 1.5 or later 107 #if (SVN_VER_MAJOR == 1 && SVN_VER_MINOR >= 5) || SVN_VER_MAJOR > 1 108 #define PYSVN_HAS_SVN__DEPTH_PARAMETER 109 #define PYSVN_HAS_CLIENT_ADD4 110 #define PYSVN_HAS_CLIENT_ADD_TO_CHANGELIST 111 #define PYSVN_HAS_SVN_CLIENT_BLAME_RECEIVER2_T QQQ 112 #define PYSVN_HAS_CLIENT_ANNOTATE4 113 #define PYSVN_HAS_CLIENT_CHECKOUT3 114 #define PYSVN_HAS_CLIENT_COMMIT4 115 #define PYSVN_HAS_CLIENT_COPY4 116 #define PYSVN_HAS_SVN_CLIENT_CTX_T__CONFLICT_FUNC 117 #define PYSVN_HAS_SVN_CLIENT_CTX_T__LOG_MSG_FUNC3 QQQ 118 #define PYSVN_HAS_SVN_CLIENT_CTX_T__MIMETYPES_MAP QQQ 119 #define PYSVN_HAS_CLIENT_DELETE3 120 #define PYSVN_HAS_CLIENT_DIFF4 121 #define PYSVN_HAS_CLIENT_DIFF_PEG4 122 #define PYSVN_HAS_CLIENT_DIFF_SUMMARIZE2 123 #define PYSVN_HAS_CLIENT_DIFF_SUMMARIZE_PEG2 124 #define PYSVN_HAS_CLIENT_EXPORT4 125 #define PYSVN_HAS_CLIENT_GET_CHANGELIST 126 #define PYSVN_HAS_CLIENT_GET_CHANGELIST_STREAMY QQQ 127 #define PYSVN_HAS_SVN_CLIENT_GET_COMMIT_LOG3_T QQQ 128 #define PYSVN_HAS_CLIENT_IMPORT3 129 #define PYSVN_HAS_CLIENT_INFO2 130 #define PYSVN_HAS_CLIENT_LIST2 131 #define PYSVN_HAS_CLIENT_LOG4 132 #define PYSVN_HAS_CLIENT_MERGE3 133 #define PYSVN_HAS_CLIENT_MERGE_REINTEGRATE 134 #define PYSVN_HAS_CLIENT_MERGEINFO_GET_AVAILABLE QQQ 135 #define PYSVN_HAS_CLIENT_MERGEINFO_GET_MERGED QQQ 136 #define PYSVN_HAS_CLIENT_MERGE_PEG3 QQQ 137 #define PYSVN_HAS_CLIENT_MKDIR3 138 #define PYSVN_HAS_CLIENT_MOVE5 139 #define PYSVN_HAS_CLIENT_PROPGET3 140 #define PYSVN_HAS_CLIENT_PROPLIST3 141 #define PYSVN_HAS_CLIENT_PROPSET3 142 #define PYSVN_HAS_CLIENT_REMOVE_FROM_CHANGELISTS 143 #define PYSVN_HAS_CLIENT_RESOLVE 144 #define PYSVN_HAS_CLIENT_REVERT2 145 #define PYSVN_HAS_CLIENT_ROOT_URL_FROM_PATH 146 #define PYSVN_HAS_CLIENT_STATUS3 147 #define PYSVN_HAS_CLIENT_SUGGEST_MERGE_SOURCES QQQ 148 #define PYSVN_HAS_CLIENT_SWITCH2 149 #define PYSVN_HAS_CLIENT_UPDATE3 150 #define PYSVN_HAS_SVN_INFO_T__CHANGELIST 151 #define PYSVN_HAS_SVN_INFO_T__SIZES 152 #define PYSVN_HAS_SVN_WC_NOTIFY_ACTION_T__1_5 QQQ 153 #define PYSVN_HAS_SVN_WC_CONFLICT_CHOICE_T 154 #endif 155 156 // SVn 1.6 or later 157 #if (SVN_VER_MAJOR == 1 && SVN_VER_MINOR >= 6) || SVN_VER_MAJOR > 1 158 #define PYSVN_HAS_SVN_1_6 159 #define PYSVN_HAS_CLIENT_COPY5 160 #define PYSVN_HAS_IO_OPEN_UNIQUE_FILE3 161 #define PYSVN_HAS_CLIENT_LOG5 162 #define PYSVN_HAS_CLIENT_REVPROP_SET2 1 163 #define PYSVN_HAS_CLIENT_STATUS4 164 #define PYSVN_HAS_AUTH_GET_SIMPLE_PROVIDER2 165 #define PYSVN_HAS_AUTH_GET_SSL_CLIENT_CERT_PW_FILE_PROVIDER2 166 #define PYSVN_HAS_SVN_CLIENT_CTX_T__CONFLICT_FUNC_1_6 167 #define PYSVN_HAS_SVN_WC_OPERATION_T 168 #define PYSVN_HAS_SVN_WC_CONFLICT_RESULT_T__SAVE_MERGED 169 #define PYSVN_HAS_SVN_AUTH_GET_PLATFORM_SPECIFIC_CLIENT_PROVIDERS 170 #endif 171 172 // SVN 1.7 or later 173 #if (SVN_VER_MAJOR == 1 && SVN_VER_MINOR >= 7) || SVN_VER_MAJOR > 1 174 #define PYSVN_HAS_SVN_1_7 175 #define PYSVN_HAS_COMMIT_CALLBACK2_T qqq 176 #define PYSNV_HAS_REPOS_OPEN2 1 177 #define PYSNV_HAS_IO_REMOVE_FILE2 1 178 #define PYSVN_HAS_CLIENT_ANNOTATE5 1 179 #define PYSVN_HAS_CLIENT_COMMIT5 1 180 #define PYSVN_HAS_CLIENT_COPY6 1 181 #define PYSVN_HAS_CLIENT_DELETE4 1 182 #define PYSVN_HAS_CLIENT_DIFF5 1 183 #define PYSVN_HAS_CLIENT_DIFF_PEG5 1 184 #define PYSVN_HAS_CLIENT_EXPORT5 QQQ 185 #define PYSVN_HAS_CLIENT_GET_WC_ROOT QQQ 186 #define PYSVN_HAS_CLIENT_IMPORT4 QQQ 187 #define PYSVN_HAS_CLIENT_INFO2_T QQQ 188 #define PYSVN_HAS_CLIENT_INFO3 QQQ 189 #define PYSVN_HAS_CLIENT_INFO_RECEIVER2_T QQQ 190 #define PYSVN_HAS_CLIENT_MERGE4 QQQ 191 #define PYSVN_HAS_CLIENT_MERGEINFO_LOG QQQ 192 #define PYSVN_HAS_CLIENT_MERGE_PEG4 1 193 #define PYSVN_HAS_CLIENT_MIN_MAX_REVISIONS QQQ 194 #define PYSVN_HAS_CLIENT_MKDIR4 1 195 #define PYSVN_HAS_CLIENT_MOVE6 1 196 #define PYSVN_HAS_CLIENT_PATCH QQQ 197 #define PYSVN_HAS_CLIENT_PATCH_FUNC_T QQQ 198 #define PYSVN_HAS_CLIENT_PROPGET4 QQQ 199 #define PYSVN_HAS_CLIENT_PROPSET_LOCAL 1 200 #define PYSVN_HAS_CLIENT_PROPSET_REMOTE 1 201 #define PYSVN_HAS_CLIENT_RELOCATE2 QQQ 202 #define PYSVN_HAS_CLIENT_STATUS5 1 203 #define PYSVN_HAS_CLIENT_STATUS_T 1 204 #define PYSVN_HAS_CLIENT_SWITCH3 1 205 #define PYSVN_HAS_CLIENT_UPDATE4 QQQ 206 #define PYSVN_HAS_CLIENT_UPGRADE QQQ 207 #define PYSVN_HAS_CLIENT_URL_FROM_PATH2 QQQ 208 #define PYSVN_HAS_CLIENT_UUID_FROM_PATH2 QQQ 209 #define PYSVN_HAS_FS_CHANGE_REV_PROP2 QQQ 210 #endif 211 212 // SVN 1.8 or later 213 #if (SVN_VER_MAJOR == 1 && SVN_VER_MINOR >= 8) || SVN_VER_MAJOR > 1 214 #define PYSVN_HAS_SVN_1_8 215 #define PYSVN_HAS_CLIENT_ADD5 1 216 #define PYSVN_HAS_CLIENT_COMMIT6 1 217 #define PYSVN_HAS_CLIENT_CLEANUP 1 218 #define PYSVN_HAS_CLIENT_CREATE_CONTEXT2 1 219 #define PYSVN_HAS_CLIENT_DIFF6 QQQ 220 #define PYSVN_HAS_CLIENT_DIFF_PEG6 QQQ 221 #define PYSVN_HAS_CLIENT_GET_MERGING_SUMMARY QQQ 222 #define PYSVN_HAS_CLIENT_GET_REPOS_ROOT 1 223 #define PYSVN_HAS_CLIENT_IMPORT5 QQQ 224 #define PYSVN_HAS_CLIENT_LIST3 1 225 #define PYSVN_HAS_CLIENT_MERGE5 QQQ 226 #define PYSVN_HAS_CLIENT_MERGEINFO_LOG2 QQQ 227 #define PYSVN_HAS_CLIENT_MERGE_PEG5 QQQ 228 #define PYSVN_HAS_CLIENT_MOVE7 1 229 #define PYSVN_HAS_CLIENT_PROPGET5 1 230 #define PYSVN_HAS_CLIENT_PROPLIST4 QQQ 231 #endif 232 233 // SVN 1.9 or later 234 #if (SVN_VER_MAJOR == 1 && SVN_VER_MINOR >= 9) || SVN_VER_MAJOR > 1 235 #define PYSVN_HAS_SVN_1_9 236 #define PYSVN_HAS_STREAM_READ_FULL 1 237 #define PYSVN_HAS_CLIENT_CAT3 1 238 #define PYSVN_HAS_CLIENT_CLEANUP2 1 239 #define PYSVN_HAS_CLIENT_COPY7 1 240 #define PYSVN_HAS_CLIENT_INFO4 1 241 #define PYSVN_HAS_CLIENT_REVERT3 1 242 #define PYSVN_HAS_CLIENT_STATUS6 1 243 #define PYSVN_HAS_CLIENT_VACUUM 1 244 #define PYSVN_HAS_REPOS_OPEN3 1 245 #endif 246 247 // SVN 1.10 or later 248 #if (SVN_VER_MAJOR == 1 && SVN_VER_MINOR >= 10) || SVN_VER_MAJOR > 1 249 #define PYSVN_HAS_SVN_1_10 250 #define PYSVN_HAS_CLIENT_LIST4 1 251 // Need to support svn_client_conflict_option_id_t 252 #define PYSVN_HAS_CLIENT_conflict_option_get_moved_to_repos_relpath_candidates 1 253 #define PYSVN_HAS_CLIENT_conflict_option_set_moved_to_repos_relpath 1 254 #define PYSVN_HAS_CLIENT_conflict_option_get_moved_to_repos_abspath_candidates 1 255 #define PYSVN_HAS_CLIENT_conflict_option_set_moved_to_repos_abspath 1 256 #endif 257 258 // SVN 1.11 or later 259 #if (SVN_VER_MAJOR == 1 && SVN_VER_MINOR >= 11) || SVN_VER_MAJOR > 1 260 #define PYSVN_HAS_SVN_1_11 261 #define PYSVN_HAS_CLIENT_DIFF7 1 262 #define PYSVN_HAS_CLIENT_REVERT4 1 263 // Need to support svn_client_conflict_option_id_t 264 #define PYSVN_HAS_CLIENT_conflict_option_get_moved_to_repos_relpath_candidates2 1 265 #define PYSVN_HAS_CLIENT_conflict_option_set_moved_to_repos_relpath2 1 266 #define PYSVN_HAS_CLIENT_conflict_option_get_moved_to_repos_abspath_candidates2 1 267 #define PYSVN_HAS_CLIENT_conflict_option_set_moved_to_repos_abspath2 1 268 #endif 269 270 // SVN 1.12 or later 271 #if (SVN_VER_MAJOR == 1 && SVN_VER_MINOR >= 12) || SVN_VER_MAJOR > 1 272 #define PYSVN_HAS_SVN_1_12 273 #define PYSVN_HAS_CLIENT_ANNOTATE6 1 274 #endif 275 276 #if defined( PYSVN_HAS_CLIENT_STATUS3 ) 277 typedef svn_wc_status2_t pysvn_wc_status_t; 278 279 #elif defined( PYSVN_HAS_CLIENT_STATUS2 ) 280 typedef svn_wc_status2_t pysvn_wc_status_t; 281 282 #else 283 typedef svn_wc_status_t pysvn_wc_status_t; 284 #endif 285 286 #if defined( PYSVN_HAS_SVN_COMMIT_INFO_T ) 287 typedef svn_commit_info_t pysvn_commit_info_t; 288 #else 289 typedef svn_client_commit_info_t pysvn_commit_info_t; 290 #endif 291 292 class SvnPool; 293 class SvnContext; 294 class SvnTransaction; 295 296 class SvnException 297 { 298 public: 299 SvnException( svn_error_t *error ); 300 SvnException( const SvnException &other ); 301 302 virtual ~SvnException(); 303 304 // access methods 305 Py::String &message(); 306 Py::Object &pythonExceptionArg( int style ); 307 apr_status_t code(); 308 309 private: 310 int m_code; 311 Py::String m_message; 312 Py::Object m_exception_arg; 313 314 private: 315 SvnException(); 316 SvnException &operator=( const SvnException & ); 317 }; 318 319 320 class SvnPool 321 { 322 public: 323 SvnPool( SvnContext &ctx ); 324 SvnPool( SvnTransaction &txn ); 325 ~SvnPool(); 326 327 operator apr_pool_t *() const; 328 329 private: 330 apr_pool_t *m_pool; 331 }; 332 333 class SvnContext 334 { 335 public: 336 SvnContext( const std::string &config_dir="" ); 337 virtual ~SvnContext(); 338 339 operator svn_client_ctx_t *(); 340 svn_client_ctx_t *ctx(); 341 castBaton(void * baton_)342 static SvnContext *castBaton( void *baton_ ) { return static_cast<SvnContext *>( baton_ ); } 343 344 // only use this pool for data that has a life time 345 // that matches the life time of the context 346 apr_pool_t *getContextPool(); 347 348 // 349 // this method will be called to retrieve 350 // authentication information 351 // 352 // WORKAROUND FOR apr_xlate PROBLEM: 353 // STRINGS ALREADY HAVE TO BE UTF8!!! 354 // 355 // @retval true continue 356 // 357 void installGetLogin( bool install ); 358 virtual bool contextGetLogin 359 ( 360 const std::string &realm, 361 std::string &username, 362 std::string &password, 363 bool &may_save 364 ) = 0; 365 366 // 367 // this method will be called to notify about 368 // the progress of an ongoing action 369 // 370 void installNotify( bool install ); 371 #if defined( PYSVN_HAS_CONTEXT_NOTIFY2 ) 372 virtual void contextNotify2 373 ( 374 const svn_wc_notify_t *notify, 375 apr_pool_t *pool 376 ) = 0; 377 #else 378 virtual void contextNotify 379 ( 380 const char *path, 381 svn_wc_notify_action_t action, 382 svn_node_kind_t kind, 383 const char *mime_type, 384 svn_wc_notify_state_t content_state, 385 svn_wc_notify_state_t prop_state, 386 svn_revnum_t revision 387 ) = 0; 388 #endif 389 390 391 #if defined( PYSVN_HAS_CONTEXT_PROGRESS ) 392 void installProgress( bool install ); 393 virtual void contextProgress 394 ( 395 apr_off_t progress, 396 apr_off_t total 397 ) = 0; 398 #endif 399 400 #if defined( PYSVN_HAS_SVN_CLIENT_CTX_T__CONFLICT_FUNC ) 401 void installConflictResolver( bool install ); 402 virtual bool contextConflictResolver 403 ( 404 svn_wc_conflict_result_t **result, 405 const svn_wc_conflict_description_t *description, 406 apr_pool_t *pool 407 ) = 0; 408 #endif 409 410 // 411 // this method will be called periodically to allow 412 // the app to cancel long running operations 413 // 414 // @return cancel action? 415 // @retval true cancel 416 // 417 void installCancel( bool install ); 418 virtual bool contextCancel 419 ( 420 ) = 0; 421 422 // 423 // this method will be called to retrieve 424 // a log message 425 // 426 virtual bool contextGetLogMessage 427 ( 428 std::string &msg 429 ) = 0; 430 431 // 432 // this method is called if there is ssl server 433 // information, that has to be confirmed by the user 434 // 435 // @param data 436 // @return @a SslServerTrustAnswer 437 // 438 virtual bool contextSslServerTrustPrompt 439 ( 440 const svn_auth_ssl_server_cert_info_t &info, 441 const std::string &relam, 442 apr_uint32_t &acceptedFailures, 443 bool &accept_permanent 444 ) = 0; 445 446 // 447 // this method is called to retrieve client side 448 // information 449 // 450 virtual bool contextSslClientCertPrompt 451 ( 452 std::string &cert_file, const std::string &realm, bool &may_save 453 ) = 0; 454 455 // 456 // this method is called to retrieve the password 457 // for the certificate 458 // 459 // @param password 460 // 461 virtual bool contextSslClientCertPwPrompt 462 ( 463 std::string &password, 464 const std::string &realm, 465 bool &may_save 466 ) = 0; 467 468 private: 469 apr_pool_t *m_pool; 470 svn_client_ctx_t *m_context; 471 const char *m_config_dir; 472 }; 473 474 class SvnTransaction 475 { 476 public: 477 SvnTransaction(); 478 ~SvnTransaction(); 479 480 svn_error_t *init( const std::string &repos_path, const std::string &transaction, 481 bool is_revision ); 482 483 operator svn_fs_txn_t *(); 484 svn_fs_txn_t *transaction(); 485 operator svn_fs_t *(); 486 operator svn_repos_t *(); 487 svn_revnum_t revision(); is_revision() const488 bool is_revision() const { return m_txn == NULL; }; 489 svn_error_t *root( svn_fs_root_t **root, apr_pool_t *pool ); 490 491 private: 492 apr_pool_t *m_pool; 493 svn_repos_t *m_repos; 494 svn_fs_t *m_fs; 495 svn_fs_txn_t *m_txn; 496 char *m_txn_name; 497 svn_revnum_t m_rev_id; 498 }; 499 500 #endif // __PYSVN_SVNENV__ 501