comparison push_cmd.py @ 70:49b7cbe4c8e3

push_cmd: handle copies at file level Mercurial store knows only file-level copies, directory copies are handle with heuristics. Implement the former one in svn backends.
author Patrick Mezard <pmezard@gmail.com>
date Wed, 05 Nov 2008 13:37:08 +0100
parents b33940d54fe2
children 6c9b7cf1c5aa
comparison
equal deleted inserted replaced
69:63ece4ea25c9 70:49b7cbe4c8e3
99 if parent_branch and parent_branch != 'default': 99 if parent_branch and parent_branch != 'default':
100 branch_path = 'branches/%s' % parent_branch 100 branch_path = 'branches/%s' % parent_branch
101 101
102 added_dirs = [] 102 added_dirs = []
103 props = {} 103 props = {}
104 copies = {}
104 for file in rev_ctx.files(): 105 for file in rev_ctx.files():
105 new_data = base_data = '' 106 new_data = base_data = ''
106 action = '' 107 action = ''
107 if file in rev_ctx: 108 if file in rev_ctx:
108 new_data = rev_ctx.filectx(file).data() 109 fctx = rev_ctx.filectx(file)
110 new_data = fctx.data()
109 111
110 if 'x' in rev_ctx.filectx(file).flags(): 112 if 'x' in fctx.flags():
111 props.setdefault(file, {})['svn:executable'] = '*' 113 props.setdefault(file, {})['svn:executable'] = '*'
112 if 'l' in rev_ctx.filectx(file).flags(): 114 if 'l' in fctx.flags():
113 props.setdefault(file, {})['svn:special'] = '*' 115 props.setdefault(file, {})['svn:special'] = '*'
114 116
115 if file not in parent: 117 if file not in parent:
118 renamed = fctx.renamed()
119 if renamed:
120 # TODO current model (and perhaps svn model) does not support
121 # this kind of renames: a -> b, b -> c
122 copies[file] = renamed[0]
123 base_data = parent[renamed[0]].data()
124
116 action = 'add' 125 action = 'add'
117 dirname = '/'.join(file.split('/')[:-1] + ['']) 126 dirname = '/'.join(file.split('/')[:-1] + [''])
118 # check for new directories 127 # check for new directories
119 if not list(parent.walk(util.PrefixMatch(dirname))): 128 if not list(parent.walk(util.PrefixMatch(dirname))):
120 added_dirs += _findmissing(dirname, svn, branch_path) 129 added_dirs += _findmissing(dirname, svn, branch_path)
131 base_data = parent.filectx(file).data() 140 base_data = parent.filectx(file).data()
132 action = 'delete' 141 action = 'delete'
133 file_data[file] = base_data, new_data, action 142 file_data[file] = base_data, new_data, action
134 143
135 # TODO check for directory deletes here 144 # TODO check for directory deletes here
136 new_target_files = ['%s/%s' % (branch_path, f) for f in rev_ctx.files()] 145 def svnpath(p):
146 return '%s/%s' % (branch_path, p)
147
148 newcopies = {}
149 for source, dest in copies.iteritems():
150 newcopies[svnpath(source)] = (svnpath(dest), base_revision)
151
152 new_target_files = [svnpath(f) for f in rev_ctx.files()]
137 for tf, ntf in zip(rev_ctx.files(), new_target_files): 153 for tf, ntf in zip(rev_ctx.files(), new_target_files):
138 if tf in file_data: 154 if tf in file_data:
139 file_data[ntf] = file_data[tf] 155 file_data[ntf] = file_data[tf]
140 if tf in props: 156 if tf in props:
141 props[ntf] = props[tf] 157 props[ntf] = props[tf]
147 added_dirs = ['%s/%s' % (branch_path, f) for f in added_dirs] 163 added_dirs = ['%s/%s' % (branch_path, f) for f in added_dirs]
148 added_dirs = set(added_dirs) 164 added_dirs = set(added_dirs)
149 new_target_files += added_dirs 165 new_target_files += added_dirs
150 try: 166 try:
151 svn.commit(new_target_files, rev_ctx.description(), file_data, 167 svn.commit(new_target_files, rev_ctx.description(), file_data,
152 base_revision, set(added_dirs), props) 168 base_revision, set(added_dirs), props, newcopies)
153 except core.SubversionException, e: 169 except core.SubversionException, e:
154 if hasattr(e, 'apr_err') and e.apr_err == 160028: 170 if hasattr(e, 'apr_err') and e.apr_err == 160028:
155 raise merc_util.Abort('Base text was out of date, maybe rebase?') 171 raise merc_util.Abort('Base text was out of date, maybe rebase?')
156 else: 172 else:
157 raise 173 raise