diff options
-rw-r--r-- | manifest_xml.py | 16 | ||||
-rw-r--r-- | project.py | 49 | ||||
-rwxr-xr-x | repo | 8 |
3 files changed, 59 insertions, 14 deletions
diff --git a/manifest_xml.py b/manifest_xml.py index 3c8fadd6..e2f58e62 100644 --- a/manifest_xml.py +++ b/manifest_xml.py | |||
@@ -261,6 +261,12 @@ class XmlManifest(object): | |||
261 | ce.setAttribute('dest', c.dest) | 261 | ce.setAttribute('dest', c.dest) |
262 | e.appendChild(ce) | 262 | e.appendChild(ce) |
263 | 263 | ||
264 | for l in p.linkfiles: | ||
265 | le = doc.createElement('linkfile') | ||
266 | le.setAttribute('src', l.src) | ||
267 | le.setAttribute('dest', l.dest) | ||
268 | e.appendChild(le) | ||
269 | |||
264 | default_groups = ['all', 'name:%s' % p.name, 'path:%s' % p.relpath] | 270 | default_groups = ['all', 'name:%s' % p.name, 'path:%s' % p.relpath] |
265 | egroups = [g for g in p.groups if g not in default_groups] | 271 | egroups = [g for g in p.groups if g not in default_groups] |
266 | if egroups: | 272 | if egroups: |
@@ -765,6 +771,8 @@ class XmlManifest(object): | |||
765 | for n in node.childNodes: | 771 | for n in node.childNodes: |
766 | if n.nodeName == 'copyfile': | 772 | if n.nodeName == 'copyfile': |
767 | self._ParseCopyFile(project, n) | 773 | self._ParseCopyFile(project, n) |
774 | if n.nodeName == 'linkfile': | ||
775 | self._ParseLinkFile(project, n) | ||
768 | if n.nodeName == 'annotation': | 776 | if n.nodeName == 'annotation': |
769 | self._ParseAnnotation(project, n) | 777 | self._ParseAnnotation(project, n) |
770 | if n.nodeName == 'project': | 778 | if n.nodeName == 'project': |
@@ -814,6 +822,14 @@ class XmlManifest(object): | |||
814 | # dest is relative to the top of the tree | 822 | # dest is relative to the top of the tree |
815 | project.AddCopyFile(src, dest, os.path.join(self.topdir, dest)) | 823 | project.AddCopyFile(src, dest, os.path.join(self.topdir, dest)) |
816 | 824 | ||
825 | def _ParseLinkFile(self, project, node): | ||
826 | src = self._reqatt(node, 'src') | ||
827 | dest = self._reqatt(node, 'dest') | ||
828 | if not self.IsMirror: | ||
829 | # src is project relative; | ||
830 | # dest is relative to the top of the tree | ||
831 | project.AddLinkFile(src, dest, os.path.join(self.topdir, dest)) | ||
832 | |||
817 | def _ParseAnnotation(self, project, node): | 833 | def _ParseAnnotation(self, project, node): |
818 | name = self._reqatt(node, 'name') | 834 | name = self._reqatt(node, 'name') |
819 | value = self._reqatt(node, 'value') | 835 | value = self._reqatt(node, 'value') |
@@ -231,6 +231,30 @@ class _CopyFile: | |||
231 | except IOError: | 231 | except IOError: |
232 | _error('Cannot copy file %s to %s', src, dest) | 232 | _error('Cannot copy file %s to %s', src, dest) |
233 | 233 | ||
234 | class _LinkFile: | ||
235 | def __init__(self, src, dest, abssrc, absdest): | ||
236 | self.src = src | ||
237 | self.dest = dest | ||
238 | self.abs_src = abssrc | ||
239 | self.abs_dest = absdest | ||
240 | |||
241 | def _Link(self): | ||
242 | src = self.abs_src | ||
243 | dest = self.abs_dest | ||
244 | # link file if it does not exist or is out of date | ||
245 | if not os.path.islink(dest) or os.readlink(dest) != src: | ||
246 | try: | ||
247 | # remove existing file first, since it might be read-only | ||
248 | if os.path.exists(dest): | ||
249 | os.remove(dest) | ||
250 | else: | ||
251 | dest_dir = os.path.dirname(dest) | ||
252 | if not os.path.isdir(dest_dir): | ||
253 | os.makedirs(dest_dir) | ||
254 | os.symlink(src, dest) | ||
255 | except IOError: | ||
256 | _error('Cannot link file %s to %s', src, dest) | ||
257 | |||
234 | class RemoteSpec(object): | 258 | class RemoteSpec(object): |
235 | def __init__(self, | 259 | def __init__(self, |
236 | name, | 260 | name, |
@@ -555,6 +579,7 @@ class Project(object): | |||
555 | 579 | ||
556 | self.snapshots = {} | 580 | self.snapshots = {} |
557 | self.copyfiles = [] | 581 | self.copyfiles = [] |
582 | self.linkfiles = [] | ||
558 | self.annotations = [] | 583 | self.annotations = [] |
559 | self.config = GitConfig.ForRepository( | 584 | self.config = GitConfig.ForRepository( |
560 | gitdir = self.gitdir, | 585 | gitdir = self.gitdir, |
@@ -1040,7 +1065,7 @@ class Project(object): | |||
1040 | except OSError as e: | 1065 | except OSError as e: |
1041 | print("warn: Cannot remove archive %s: " | 1066 | print("warn: Cannot remove archive %s: " |
1042 | "%s" % (tarpath, str(e)), file=sys.stderr) | 1067 | "%s" % (tarpath, str(e)), file=sys.stderr) |
1043 | self._CopyFiles() | 1068 | self._CopyAndLinkFiles() |
1044 | return True | 1069 | return True |
1045 | 1070 | ||
1046 | if is_new is None: | 1071 | if is_new is None: |
@@ -1103,9 +1128,11 @@ class Project(object): | |||
1103 | def PostRepoUpgrade(self): | 1128 | def PostRepoUpgrade(self): |
1104 | self._InitHooks() | 1129 | self._InitHooks() |
1105 | 1130 | ||
1106 | def _CopyFiles(self): | 1131 | def _CopyAndLinkFiles(self): |
1107 | for copyfile in self.copyfiles: | 1132 | for copyfile in self.copyfiles: |
1108 | copyfile._Copy() | 1133 | copyfile._Copy() |
1134 | for linkfile in self.linkfiles: | ||
1135 | linkfile._Link() | ||
1109 | 1136 | ||
1110 | def GetCommitRevisionId(self): | 1137 | def GetCommitRevisionId(self): |
1111 | """Get revisionId of a commit. | 1138 | """Get revisionId of a commit. |
@@ -1152,7 +1179,7 @@ class Project(object): | |||
1152 | 1179 | ||
1153 | def _doff(): | 1180 | def _doff(): |
1154 | self._FastForward(revid) | 1181 | self._FastForward(revid) |
1155 | self._CopyFiles() | 1182 | self._CopyAndLinkFiles() |
1156 | 1183 | ||
1157 | head = self.work_git.GetHead() | 1184 | head = self.work_git.GetHead() |
1158 | if head.startswith(R_HEADS): | 1185 | if head.startswith(R_HEADS): |
@@ -1188,7 +1215,7 @@ class Project(object): | |||
1188 | except GitError as e: | 1215 | except GitError as e: |
1189 | syncbuf.fail(self, e) | 1216 | syncbuf.fail(self, e) |
1190 | return | 1217 | return |
1191 | self._CopyFiles() | 1218 | self._CopyAndLinkFiles() |
1192 | return | 1219 | return |
1193 | 1220 | ||
1194 | if head == revid: | 1221 | if head == revid: |
@@ -1210,7 +1237,7 @@ class Project(object): | |||
1210 | except GitError as e: | 1237 | except GitError as e: |
1211 | syncbuf.fail(self, e) | 1238 | syncbuf.fail(self, e) |
1212 | return | 1239 | return |
1213 | self._CopyFiles() | 1240 | self._CopyAndLinkFiles() |
1214 | return | 1241 | return |
1215 | 1242 | ||
1216 | upstream_gain = self._revlist(not_rev(HEAD), revid) | 1243 | upstream_gain = self._revlist(not_rev(HEAD), revid) |
@@ -1283,12 +1310,12 @@ class Project(object): | |||
1283 | if cnt_mine > 0 and self.rebase: | 1310 | if cnt_mine > 0 and self.rebase: |
1284 | def _dorebase(): | 1311 | def _dorebase(): |
1285 | self._Rebase(upstream = '%s^1' % last_mine, onto = revid) | 1312 | self._Rebase(upstream = '%s^1' % last_mine, onto = revid) |
1286 | self._CopyFiles() | 1313 | self._CopyAndLinkFiles() |
1287 | syncbuf.later2(self, _dorebase) | 1314 | syncbuf.later2(self, _dorebase) |
1288 | elif local_changes: | 1315 | elif local_changes: |
1289 | try: | 1316 | try: |
1290 | self._ResetHard(revid) | 1317 | self._ResetHard(revid) |
1291 | self._CopyFiles() | 1318 | self._CopyAndLinkFiles() |
1292 | except GitError as e: | 1319 | except GitError as e: |
1293 | syncbuf.fail(self, e) | 1320 | syncbuf.fail(self, e) |
1294 | return | 1321 | return |
@@ -1301,6 +1328,12 @@ class Project(object): | |||
1301 | abssrc = os.path.join(self.worktree, src) | 1328 | abssrc = os.path.join(self.worktree, src) |
1302 | self.copyfiles.append(_CopyFile(src, dest, abssrc, absdest)) | 1329 | self.copyfiles.append(_CopyFile(src, dest, abssrc, absdest)) |
1303 | 1330 | ||
1331 | def AddLinkFile(self, src, dest, absdest): | ||
1332 | # dest should already be an absolute path, but src is project relative | ||
1333 | # make src an absolute path | ||
1334 | abssrc = os.path.join(self.worktree, src) | ||
1335 | self.linkfiles.append(_LinkFile(src, dest, abssrc, absdest)) | ||
1336 | |||
1304 | def AddAnnotation(self, name, value, keep): | 1337 | def AddAnnotation(self, name, value, keep): |
1305 | self.annotations.append(_Annotation(name, value, keep)) | 1338 | self.annotations.append(_Annotation(name, value, keep)) |
1306 | 1339 | ||
@@ -2201,7 +2234,7 @@ class Project(object): | |||
2201 | if GitCommand(self, cmd).Wait() != 0: | 2234 | if GitCommand(self, cmd).Wait() != 0: |
2202 | raise GitError("cannot initialize work tree") | 2235 | raise GitError("cannot initialize work tree") |
2203 | 2236 | ||
2204 | self._CopyFiles() | 2237 | self._CopyAndLinkFiles() |
2205 | 2238 | ||
2206 | def _gitdir_path(self, path): | 2239 | def _gitdir_path(self, path): |
2207 | return os.path.realpath(os.path.join(self.gitdir, path)) | 2240 | return os.path.realpath(os.path.join(self.gitdir, path)) |
@@ -114,6 +114,7 @@ import errno | |||
114 | import optparse | 114 | import optparse |
115 | import os | 115 | import os |
116 | import re | 116 | import re |
117 | import shutil | ||
117 | import stat | 118 | import stat |
118 | import subprocess | 119 | import subprocess |
119 | import sys | 120 | import sys |
@@ -741,12 +742,7 @@ def main(orig_args): | |||
741 | try: | 742 | try: |
742 | _Init(args) | 743 | _Init(args) |
743 | except CloneFailure: | 744 | except CloneFailure: |
744 | for root, dirs, files in os.walk(repodir, topdown=False): | 745 | shutil.rmtree(repodir, ignore_errors=True) |
745 | for name in files: | ||
746 | os.remove(os.path.join(root, name)) | ||
747 | for name in dirs: | ||
748 | os.rmdir(os.path.join(root, name)) | ||
749 | os.rmdir(repodir) | ||
750 | sys.exit(1) | 746 | sys.exit(1) |
751 | repo_main, rel_repo_dir = _FindRepo() | 747 | repo_main, rel_repo_dir = _FindRepo() |
752 | else: | 748 | else: |