##// END OF EJS Templates
fix(svn): svn events fixes
super-admin -
r1261:0f8db01d default
parent child Browse files
Show More
@@ -0,0 +1,111 b''
1 # RhodeCode VCSServer provides access to different vcs backends via network.
2 # Copyright (C) 2014-2023 RhodeCode GmbH
3 #
4 # This program is free software; you can redistribute it and/or modify
5 # it under the terms of the GNU General Public License as published by
6 # the Free Software Foundation; either version 3 of the License, or
7 # (at your option) any later version.
8 #
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
13 #
14 # You should have received a copy of the GNU General Public License
15 # along with this program; if not, write to the Free Software Foundation,
16 # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17
18 import logging
19 import redis
20
21 from ..lib import rc_cache
22 from ..lib.ext_json import json
23
24
25 log = logging.getLogger(__name__)
26
27 redis_client = None
28
29
30 class RedisTxnClient:
31
32 def __init__(self, url):
33 self.url = url
34 self._create_client(url)
35
36 def _create_client(self, url):
37 connection_pool = redis.ConnectionPool.from_url(url)
38 self.writer_client = redis.StrictRedis(
39 connection_pool=connection_pool
40 )
41 self.reader_client = self.writer_client
42
43 def set(self, key, value):
44 self.writer_client.set(key, value)
45
46 def get(self, key):
47 return self.reader_client.get(key)
48
49 def delete(self, key):
50 self.writer_client.delete(key)
51
52
53 def get_redis_client(url=''):
54
55 global redis_client
56 if redis_client is not None:
57 return redis_client
58 if not url:
59 from vcsserver import CONFIG
60 url = CONFIG['vcs.svn.redis_conn']
61 redis_client = RedisTxnClient(url)
62 return redis_client
63
64
65 def get_txn_id_data_key(repo_path, svn_txn_id):
66 log.debug('svn-txn-id: %s, obtaining data path', svn_txn_id)
67 repo_key = rc_cache.utils.compute_key_from_params(repo_path)
68 final_key = f'{repo_key}.{svn_txn_id}.svn_txn_id'
69 log.debug('computed final key: %s', final_key)
70
71 return final_key
72
73
74 def store_txn_id_data(repo_path, svn_txn_id, data_dict):
75 log.debug('svn-txn-id: %s, storing data', svn_txn_id)
76
77 if not svn_txn_id:
78 log.warning('Cannot store txn_id because it is empty')
79 return
80
81 redis_conn = get_redis_client()
82
83 store_key = get_txn_id_data_key(repo_path, svn_txn_id)
84 store_data = json.dumps(data_dict)
85 redis_conn.set(store_key, store_data)
86
87
88 def get_txn_id_from_store(repo_path, svn_txn_id, rm_on_read=False):
89 """
90 Reads txn_id from store and if present returns the data for callback manager
91 """
92 log.debug('svn-txn-id: %s, retrieving data', svn_txn_id)
93 redis_conn = get_redis_client()
94
95 store_key = get_txn_id_data_key(repo_path, svn_txn_id)
96 data = {}
97 redis_conn.get(store_key)
98 raw_data = 'not-set'
99 try:
100 raw_data = redis_conn.get(store_key)
101 if not raw_data:
102 raise ValueError(f'Failed to get txn_id metadata, from store: {store_key}')
103 data = json.loads(raw_data)
104 except Exception:
105 log.exception('Failed to get txn_id metadata: %s', raw_data)
106
107 if rm_on_read:
108 log.debug('Cleaning up txn_id at %s', store_key)
109 redis_conn.delete(store_key)
110
111 return data
@@ -66,6 +66,10 b' debugtoolbar.exclude_prefixes ='
66 66 ; or /usr/local/bin/rhodecode_bin/vcs_bin
67 67 core.binary_dir =
68 68
69 ; Redis connection settings for svn integrations logic
70 ; This connection string needs to be the same on ce and vcsserver
71 vcs.svn.redis_conn = redis://redis:6379/0
72
69 73 ; Custom exception store path, defaults to TMPDIR
70 74 ; This is used to store exception from RhodeCode in shared directory
71 75 #exception_tracker.store_path =
@@ -46,6 +46,10 b' use = egg:rhodecode-vcsserver'
46 46 ; or /usr/local/bin/rhodecode_bin/vcs_bin
47 47 core.binary_dir =
48 48
49 ; Redis connection settings for svn integrations logic
50 ; This connection string needs to be the same on ce and vcsserver
51 vcs.svn.redis_conn = redis://redis:6379/0
52
49 53 ; Custom exception store path, defaults to TMPDIR
50 54 ; This is used to store exception from RhodeCode in shared directory
51 55 #exception_tracker.store_path =
@@ -87,8 +87,16 b' def install_git_hooks(repo_path, bare, e'
87 87
88 88 if _rhodecode_hook or force_create:
89 89 log.debug('writing git %s hook file at %s !', h_type, _hook_file)
90 env_expand = str([
91 ('RC_INI_FILE', vcsserver.CONFIG['__file__']),
92 ('RC_CORE_BINARY_DIR', vcsserver.settings.BINARY_DIR),
93 ('RC_GIT_EXECUTABLE', vcsserver.settings.GIT_EXECUTABLE()),
94 ('RC_SVN_EXECUTABLE', vcsserver.settings.SVN_EXECUTABLE()),
95 ('RC_SVNLOOK_EXECUTABLE', vcsserver.settings.SVNLOOK_EXECUTABLE()),
96 ])
90 97 try:
91 98 with open(_hook_file, 'wb') as f:
99 template = template.replace(b'_OS_EXPAND_', safe_bytes(env_expand))
92 100 template = template.replace(b'_TMPL_', safe_bytes(vcsserver.get_version()))
93 101 template = template.replace(b'_DATE_', safe_bytes(timestamp))
94 102 template = template.replace(b'_ENV_', safe_bytes(executable))
@@ -141,17 +149,17 b' def install_svn_hooks(repo_path, executa'
141 149 log.debug('writing svn %s hook file at %s !', h_type, _hook_file)
142 150
143 151 env_expand = str([
152 ('RC_INI_FILE', vcsserver.CONFIG['__file__']),
144 153 ('RC_CORE_BINARY_DIR', vcsserver.settings.BINARY_DIR),
145 154 ('RC_GIT_EXECUTABLE', vcsserver.settings.GIT_EXECUTABLE()),
146 155 ('RC_SVN_EXECUTABLE', vcsserver.settings.SVN_EXECUTABLE()),
147 156 ('RC_SVNLOOK_EXECUTABLE', vcsserver.settings.SVNLOOK_EXECUTABLE()),
148
149 157 ])
150 158 try:
151 159 with open(_hook_file, 'wb') as f:
160 template = template.replace(b'_OS_EXPAND_', safe_bytes(env_expand))
152 161 template = template.replace(b'_TMPL_', safe_bytes(vcsserver.get_version()))
153 162 template = template.replace(b'_DATE_', safe_bytes(timestamp))
154 template = template.replace(b'_OS_EXPAND_', safe_bytes(env_expand))
155 163 template = template.replace(b'_ENV_', safe_bytes(executable))
156 164 template = template.replace(b'_PATH_', safe_bytes(path))
157 165
@@ -1,4 +1,5 b''
1 1 #!_ENV_
2
2 3 import os
3 4 import sys
4 5 path_adjust = [_PATH_]
@@ -6,6 +7,11 b' path_adjust = [_PATH_]'
6 7 if path_adjust:
7 8 sys.path = path_adjust
8 9
10 # special trick to pass in some information from rc to hooks
11 # mod_dav strips ALL env vars and we can't even access things like PATH
12 for env_k, env_v in _OS_EXPAND_:
13 os.environ[env_k] = env_v
14
9 15 try:
10 16 from vcsserver import hooks
11 17 except ImportError:
@@ -30,11 +36,13 b' def main():'
30 36
31 37 repo_path = os.getcwd()
32 38 push_data = sys.stdin.readlines()
33 os.environ['RC_HOOK_VER'] = RC_HOOK_VER
39
34 40 # os.environ is modified here by a subprocess call that
35 41 # runs git and later git executes this hook.
36 42 # Environ gets some additional info from rhodecode system
37 43 # like IP or username from basic-auth
44
45 os.environ['RC_HOOK_VER'] = RC_HOOK_VER
38 46 try:
39 47 result = hooks.git_post_receive(repo_path, push_data, os.environ)
40 48 sys.exit(result)
@@ -1,4 +1,5 b''
1 1 #!_ENV_
2
2 3 import os
3 4 import sys
4 5 path_adjust = [_PATH_]
@@ -6,6 +7,11 b' path_adjust = [_PATH_]'
6 7 if path_adjust:
7 8 sys.path = path_adjust
8 9
10 # special trick to pass in some information from rc to hooks
11 # mod_dav strips ALL env vars and we can't even access things like PATH
12 for env_k, env_v in _OS_EXPAND_:
13 os.environ[env_k] = env_v
14
9 15 try:
10 16 from vcsserver import hooks
11 17 except ImportError:
@@ -30,11 +36,13 b' def main():'
30 36
31 37 repo_path = os.getcwd()
32 38 push_data = sys.stdin.readlines()
33 os.environ['RC_HOOK_VER'] = RC_HOOK_VER
39
34 40 # os.environ is modified here by a subprocess call that
35 41 # runs git and later git executes this hook.
36 42 # Environ gets some additional info from rhodecode system
37 43 # like IP or username from basic-auth
44
45 os.environ['RC_HOOK_VER'] = RC_HOOK_VER
38 46 try:
39 47 result = hooks.git_pre_receive(repo_path, push_data, os.environ)
40 48 sys.exit(result)
@@ -7,6 +7,11 b' path_adjust = [_PATH_]'
7 7 if path_adjust:
8 8 sys.path = path_adjust
9 9
10 # special trick to pass in some information from rc to hooks
11 # mod_dav strips ALL env vars and we can't even access things like PATH
12 for env_k, env_v in _OS_EXPAND_:
13 os.environ[env_k] = env_v
14
10 15 try:
11 16 from vcsserver import hooks
12 17 except ImportError:
@@ -20,11 +25,6 b' except ImportError:'
20 25 RC_HOOK_VER = '_TMPL_'
21 26
22 27
23 # special trick to pass in some information from rc to hooks
24 # mod_dav strips ALL env vars and we can't even access things like PATH
25 for env_k, env_v in _OS_EXPAND_:
26 os.environ[env_k] = env_v
27
28 28 def main():
29 29 if hooks is None:
30 30 # exit with success if we cannot import vcsserver.hooks !!
@@ -33,13 +33,13 b' def main():'
33 33
34 34 if os.environ.get('RC_SKIP_HOOKS') or os.environ.get('RC_SKIP_SVN_HOOKS'):
35 35 sys.exit(0)
36 repo_path = os.getcwd()
36 cwd_repo_path = os.getcwd()
37 37 push_data = sys.argv[1:]
38 38
39 39 os.environ['RC_HOOK_VER'] = RC_HOOK_VER
40 40
41 41 try:
42 result = hooks.svn_post_commit(repo_path, push_data, os.environ)
42 result = hooks.svn_post_commit(cwd_repo_path, push_data, os.environ)
43 43 sys.exit(result)
44 44 except Exception as error:
45 45 # TODO: johbo: Improve handling of this special case
@@ -7,6 +7,11 b' path_adjust = [_PATH_]'
7 7 if path_adjust:
8 8 sys.path = path_adjust
9 9
10 # special trick to pass in some information from rc to hooks
11 # mod_dav strips ALL env vars and we can't even access things like PATH
12 for env_k, env_v in _OS_EXPAND_:
13 os.environ[env_k] = env_v
14
10 15 try:
11 16 from vcsserver import hooks
12 17 except ImportError:
@@ -20,11 +25,6 b' except ImportError:'
20 25 RC_HOOK_VER = '_TMPL_'
21 26
22 27
23 # special trick to pass in some information from rc to hooks
24 # mod_dav strips ALL env vars and we can't even access things like PATH
25 for env_k, env_v in _OS_EXPAND_:
26 os.environ[env_k] = env_v
27
28 28 def main():
29 29 if os.environ.get('SSH_READ_ONLY') == '1':
30 30 sys.stderr.write('Only read-only access is allowed')
@@ -37,13 +37,12 b' def main():'
37 37
38 38 if os.environ.get('RC_SKIP_HOOKS') or os.environ.get('RC_SKIP_SVN_HOOKS'):
39 39 sys.exit(0)
40 repo_path = os.getcwd()
40 cwd_repo_path = os.getcwd()
41 41 push_data = sys.argv[1:]
42 42
43 43 os.environ['RC_HOOK_VER'] = RC_HOOK_VER
44
45 44 try:
46 result = hooks.svn_pre_commit(repo_path, push_data, os.environ)
45 result = hooks.svn_pre_commit(cwd_repo_path, push_data, os.environ)
47 46 sys.exit(result)
48 47 except Exception as error:
49 48 # TODO: johbo: Improve handling of this special case
@@ -31,9 +31,10 b' from celery import Celery'
31 31 import mercurial.scmutil
32 32 import mercurial.node
33 33
34 from vcsserver import exceptions, subprocessio, settings
34 35 from vcsserver.lib.ext_json import json
35 from vcsserver import exceptions, subprocessio, settings
36 36 from vcsserver.lib.str_utils import ascii_str, safe_str
37 from vcsserver.lib.svn_txn_utils import get_txn_id_from_store
37 38 from vcsserver.remote.git_remote import Repository
38 39
39 40 celery_app = Celery('__vcsserver__')
@@ -293,20 +294,28 b' def _get_hg_env(old_rev, new_rev, txnid,'
293 294 return [(k, v) for k, v in env.items()]
294 295
295 296
297 def _get_ini_settings(ini_file):
298 from vcsserver.http_main import sanitize_settings_and_apply_defaults
299 from vcsserver.lib.config_utils import get_app_config_lightweight, configure_and_store_settings
300
301 global_config = {'__file__': ini_file}
302 ini_settings = get_app_config_lightweight(ini_file)
303 sanitize_settings_and_apply_defaults(global_config, ini_settings)
304 configure_and_store_settings(global_config, ini_settings)
305
306 return ini_settings
307
308
296 309 def _fix_hooks_executables(ini_path=''):
297 310 """
298 311 This is a trick to set proper settings.EXECUTABLE paths for certain execution patterns
299 312 especially for subversion where hooks strip entire env, and calling just 'svn' command will most likely fail
300 313 because svn is not on PATH
301 314 """
302 from vcsserver.http_main import sanitize_settings_and_apply_defaults
303 from vcsserver.lib.config_utils import get_app_config_lightweight
304
315 # set defaults, in case we can't read from ini_file
305 316 core_binary_dir = settings.BINARY_DIR or '/usr/local/bin/rhodecode_bin/vcs_bin'
306 317 if ini_path:
307
308 ini_settings = get_app_config_lightweight(ini_path)
309 ini_settings = sanitize_settings_and_apply_defaults({'__file__': ini_path}, ini_settings)
318 ini_settings = _get_ini_settings(ini_path)
310 319 core_binary_dir = ini_settings['core.binary_dir']
311 320
312 321 settings.BINARY_DIR = core_binary_dir
@@ -570,7 +579,7 b' def git_pre_receive(unused_repo_path, re'
570 579 rev_data = _parse_git_ref_lines(revision_lines)
571 580 if 'push' not in extras['hooks']:
572 581 return 0
573 _fix_hooks_executables()
582 _fix_hooks_executables(env.get('RC_INI_FILE'))
574 583
575 584 empty_commit_id = '0' * 40
576 585
@@ -616,7 +625,7 b' def git_post_receive(unused_repo_path, r'
616 625 if 'push' not in extras['hooks']:
617 626 return 0
618 627
619 _fix_hooks_executables()
628 _fix_hooks_executables(env.get('RC_INI_FILE'))
620 629
621 630 rev_data = _parse_git_ref_lines(revision_lines)
622 631
@@ -720,37 +729,8 b' def git_post_receive(unused_repo_path, r'
720 729 return status_code
721 730
722 731
723 def _get_extras_from_txn_id(path, txn_id):
724 _fix_hooks_executables()
725
726 extras = {}
727 try:
728 cmd = [settings.SVNLOOK_EXECUTABLE(), 'pget',
729 '-t', txn_id,
730 '--revprop', path, 'rc-scm-extras']
731 stdout, stderr = subprocessio.run_command(
732 cmd, env=os.environ.copy())
733 extras = json.loads(base64.urlsafe_b64decode(stdout))
734 except Exception:
735 log.exception('Failed to extract extras info from txn_id')
736
737 return extras
738
739
740 def _get_extras_from_commit_id(commit_id, path):
741 _fix_hooks_executables()
742
743 extras = {}
744 try:
745 cmd = [settings.SVNLOOK_EXECUTABLE(), 'pget',
746 '-r', commit_id,
747 '--revprop', path, 'rc-scm-extras']
748 stdout, stderr = subprocessio.run_command(
749 cmd, env=os.environ.copy())
750 extras = json.loads(base64.urlsafe_b64decode(stdout))
751 except Exception:
752 log.exception('Failed to extract extras info from commit_id')
753
732 def get_extras_from_txn_id(repo_path, txn_id):
733 extras = get_txn_id_from_store(repo_path, txn_id)
754 734 return extras
755 735
756 736
@@ -763,13 +743,18 b' def svn_pre_commit(repo_path, commit_dat'
763 743 if env.get('RC_SCM_DATA'):
764 744 extras = json.loads(env['RC_SCM_DATA'])
765 745 else:
746 ini_path = env.get('RC_INI_FILE')
747 if ini_path:
748 _get_ini_settings(ini_path)
766 749 # fallback method to read from TXN-ID stored data
767 extras = _get_extras_from_txn_id(path, txn_id)
750 extras = get_extras_from_txn_id(path, txn_id)
768 751
769 752 if not extras:
770 #TODO: temporary fix until svn txn-id changes are merged
753 raise ValueError('SVN-PRE-COMMIT: Failed to extract context data in called extras for hook execution')
754
755 if extras.get('rc_internal_commit'):
756 # special marker for internal commit, we don't call hooks client
771 757 return 0
772 raise ValueError('Failed to extract context data called extras for hook execution')
773 758
774 759 extras['hook_type'] = 'pre_commit'
775 760 extras['commit_ids'] = [txn_id]
@@ -805,13 +790,18 b' def svn_post_commit(repo_path, commit_da'
805 790 if env.get('RC_SCM_DATA'):
806 791 extras = json.loads(env['RC_SCM_DATA'])
807 792 else:
793 ini_path = env.get('RC_INI_FILE')
794 if ini_path:
795 _get_ini_settings(ini_path)
808 796 # fallback method to read from TXN-ID stored data
809 extras = _get_extras_from_commit_id(commit_id, path)
797 extras = get_extras_from_txn_id(path, txn_id)
810 798
811 if not extras:
812 #TODO: temporary fix until svn txn-id changes are merged
799 if not extras and txn_id:
800 raise ValueError('SVN-POST-COMMIT: Failed to extract context data in called extras for hook execution')
801
802 if extras.get('rc_internal_commit'):
803 # special marker for internal commit, we don't call hooks client
813 804 return 0
814 raise ValueError('Failed to extract context data called extras for hook execution')
815 805
816 806 extras['hook_type'] = 'post_commit'
817 807 extras['commit_ids'] = [commit_id]
@@ -37,20 +37,23 b' from pyramid.wsgi import wsgiapp'
37 37 from pyramid.response import Response
38 38
39 39 from vcsserver.base import BytesEnvelope, BinaryEnvelope
40 from vcsserver.lib.ext_json import json
40
41 41 from vcsserver.config.settings_maker import SettingsMaker
42 from vcsserver.lib.str_utils import safe_int
43 from vcsserver.lib.statsd_client import StatsdClient
42
44 43 from vcsserver.tweens.request_wrapper import get_headers_call_context
45 44
46 import vcsserver
47 from vcsserver import remote_wsgi, scm_app, settings, hgpatches
45 from vcsserver import remote_wsgi, scm_app, hgpatches
46 from vcsserver.server import VcsServer
48 47 from vcsserver.git_lfs.app import GIT_LFS_CONTENT_TYPE, GIT_LFS_PROTO_PAT
49 48 from vcsserver.echo_stub import remote_wsgi as remote_wsgi_stub
50 49 from vcsserver.echo_stub.echo_app import EchoApp
51 50 from vcsserver.exceptions import HTTPRepoLocked, HTTPRepoBranchProtected
52 51 from vcsserver.lib.exc_tracking import store_exception, format_exc
53 from vcsserver.server import VcsServer
52 from vcsserver.lib.str_utils import safe_int
53 from vcsserver.lib.statsd_client import StatsdClient
54 from vcsserver.lib.ext_json import json
55 from vcsserver.lib.config_utils import configure_and_store_settings
56
54 57
55 58 strict_vcs = True
56 59
@@ -94,8 +97,7 b' log = logging.getLogger(__name__)'
94 97 try:
95 98 locale.setlocale(locale.LC_ALL, '')
96 99 except locale.Error as e:
97 log.error(
98 'LOCALE ERROR: failed to set LC_ALL, fallback to LC_ALL=C, org error: %s', e)
100 log.error('LOCALE ERROR: failed to set LC_ALL, fallback to LC_ALL=C, org error: %s', e)
99 101 os.environ['LC_ALL'] = 'C'
100 102
101 103
@@ -248,25 +250,10 b' class HTTPApplication:'
248 250 log.warning("Using EchoApp for VCS operations.")
249 251 self.remote_wsgi = remote_wsgi_stub
250 252
251 self._configure_settings(global_config, settings)
253 configure_and_store_settings(global_config, settings)
252 254
253 255 self._configure()
254 256
255 def _configure_settings(self, global_config, app_settings):
256 """
257 Configure the settings module.
258 """
259 settings_merged = global_config.copy()
260 settings_merged.update(app_settings)
261
262 binary_dir = app_settings['core.binary_dir']
263
264 settings.BINARY_DIR = binary_dir
265
266 # Store the settings to make them available to other modules.
267 vcsserver.PYRAMID_SETTINGS = settings_merged
268 vcsserver.CONFIG = settings_merged
269
270 257 def _configure(self):
271 258 self.config.add_renderer(name='msgpack', factory=self._msgpack_renderer_factory)
272 259
@@ -715,6 +702,8 b' def sanitize_settings_and_apply_defaults'
715 702 'core.binary_dir', '/usr/local/bin/rhodecode_bin/vcs_bin',
716 703 default_when_empty=True, parser='string:noquote')
717 704
705 settings_maker.make_setting('vcs.svn.redis_conn', 'redis://redis:6379/0')
706
718 707 temp_store = tempfile.gettempdir()
719 708 default_cache_dir = os.path.join(temp_store, 'rc_cache')
720 709 # save default, cache dir, and use it for all backends later.
@@ -16,6 +16,8 b''
16 16 # RhodeCode Enterprise Edition, including its added features, Support services,
17 17 # and proprietary license terms, please see https://rhodecode.com/licenses/
18 18 import os
19 import vcsserver
20 import vcsserver.settings
19 21
20 22
21 23 def get_config(ini_path, **kwargs):
@@ -38,3 +40,19 b' def get_app_config(ini_path):'
38 40 """
39 41 from paste.deploy.loadwsgi import appconfig
40 42 return appconfig(f'config:{ini_path}', relative_to=os.getcwd())
43
44
45 def configure_and_store_settings(global_config, app_settings):
46 """
47 Configure the settings module.
48 """
49 settings_merged = global_config.copy()
50 settings_merged.update(app_settings)
51
52 binary_dir = app_settings['core.binary_dir']
53
54 vcsserver.settings.BINARY_DIR = binary_dir
55
56 # Store the settings to make them available to other modules.
57 vcsserver.PYRAMID_SETTINGS = settings_merged
58 vcsserver.CONFIG = settings_merged
@@ -28,7 +28,6 b' import urllib.parse'
28 28 import urllib.error
29 29 import traceback
30 30
31
32 31 import svn.client # noqa
33 32 import svn.core # noqa
34 33 import svn.delta # noqa
@@ -47,10 +46,11 b' from vcsserver.base import ('
47 46 BinaryEnvelope,
48 47 )
49 48 from vcsserver.exceptions import NoContentException
49 from vcsserver.vcs_base import RemoteBase
50 50 from vcsserver.lib.str_utils import safe_str, safe_bytes
51 51 from vcsserver.lib.type_utils import assert_bytes
52 from vcsserver.vcs_base import RemoteBase
53 52 from vcsserver.lib.svnremoterepo import svnremoterepo
53 from vcsserver.lib.svn_txn_utils import store_txn_id_data
54 54
55 55 log = logging.getLogger(__name__)
56 56
@@ -503,6 +503,11 b' class SvnRemote(RemoteBase):'
503 503 for node in removed:
504 504 TxnNodeProcessor(node, txn_root).remove()
505 505
506 svn_txn_id = safe_str(svn.fs.svn_fs_txn_name(txn))
507 full_repo_path = wire['path']
508 txn_id_data = {'svn_txn_id': svn_txn_id, 'rc_internal_commit': True}
509
510 store_txn_id_data(full_repo_path, svn_txn_id, txn_id_data)
506 511 commit_id = svn.repos.fs_commit_txn(repo, txn)
507 512
508 513 if timestamp:
General Comments 0
You need to be logged in to leave comments. Login now