diff options
| -rw-r--r-- | manifest.py | 74 | ||||
| -rw-r--r-- | project.py | 14 | ||||
| -rw-r--r-- | subcmds/manifest.py | 43 |
3 files changed, 118 insertions, 13 deletions
diff --git a/manifest.py b/manifest.py index 32a7e513..da2bb25f 100644 --- a/manifest.py +++ b/manifest.py | |||
| @@ -18,7 +18,7 @@ import sys | |||
| 18 | import xml.dom.minidom | 18 | import xml.dom.minidom |
| 19 | 19 | ||
| 20 | from git_config import GitConfig, IsId | 20 | from git_config import GitConfig, IsId |
| 21 | from project import Project, MetaProject, R_HEADS | 21 | from project import Project, MetaProject, R_HEADS, HEAD |
| 22 | from remote import Remote | 22 | from remote import Remote |
| 23 | from error import ManifestParseError | 23 | from error import ManifestParseError |
| 24 | 24 | ||
| @@ -73,6 +73,76 @@ class Manifest(object): | |||
| 73 | except OSError, e: | 73 | except OSError, e: |
| 74 | raise ManifestParseError('cannot link manifest %s' % name) | 74 | raise ManifestParseError('cannot link manifest %s' % name) |
| 75 | 75 | ||
| 76 | def _RemoteToXml(self, r, doc, root): | ||
| 77 | e = doc.createElement('remote') | ||
| 78 | root.appendChild(e) | ||
| 79 | e.setAttribute('name', r.name) | ||
| 80 | e.setAttribute('fetch', r.fetchUrl) | ||
| 81 | if r.reviewUrl is not None: | ||
| 82 | e.setAttribute('review', r.reviewUrl) | ||
| 83 | if r.projectName is not None: | ||
| 84 | e.setAttribute('project-name', r.projectName) | ||
| 85 | |||
| 86 | def Save(self, fd, peg_rev=False): | ||
| 87 | """Write the current manifest out to the given file descriptor. | ||
| 88 | """ | ||
| 89 | doc = xml.dom.minidom.Document() | ||
| 90 | root = doc.createElement('manifest') | ||
| 91 | doc.appendChild(root) | ||
| 92 | |||
| 93 | d = self.default | ||
| 94 | sort_remotes = list(self.remotes.keys()) | ||
| 95 | sort_remotes.sort() | ||
| 96 | |||
| 97 | for r in sort_remotes: | ||
| 98 | self._RemoteToXml(self.remotes[r], doc, root) | ||
| 99 | if self.remotes: | ||
| 100 | root.appendChild(doc.createTextNode('')) | ||
| 101 | |||
| 102 | have_default = False | ||
| 103 | e = doc.createElement('default') | ||
| 104 | if d.remote: | ||
| 105 | have_default = True | ||
| 106 | e.setAttribute('remote', d.remote.name) | ||
| 107 | if d.revision: | ||
| 108 | have_default = True | ||
| 109 | e.setAttribute('revision', d.revision) | ||
| 110 | if have_default: | ||
| 111 | root.appendChild(e) | ||
| 112 | root.appendChild(doc.createTextNode('')) | ||
| 113 | |||
| 114 | sort_projects = list(self.projects.keys()) | ||
| 115 | sort_projects.sort() | ||
| 116 | |||
| 117 | for p in sort_projects: | ||
| 118 | p = self.projects[p] | ||
| 119 | e = doc.createElement('project') | ||
| 120 | root.appendChild(e) | ||
| 121 | e.setAttribute('name', p.name) | ||
| 122 | if p.relpath != p.name: | ||
| 123 | e.setAttribute('path', p.relpath) | ||
| 124 | if not d.remote or p.remote.name != d.remote.name: | ||
| 125 | e.setAttribute('remote', p.remote.name) | ||
| 126 | if peg_rev: | ||
| 127 | if self.IsMirror: | ||
| 128 | e.setAttribute('revision', | ||
| 129 | p.bare_git.rev_parse(p.revision + '^0')) | ||
| 130 | else: | ||
| 131 | e.setAttribute('revision', | ||
| 132 | p.work_git.rev_parse(HEAD + '^0')) | ||
| 133 | elif not d.revision or p.revision != d.revision: | ||
| 134 | e.setAttribute('revision', p.revision) | ||
| 135 | |||
| 136 | for r in p.extraRemotes: | ||
| 137 | self._RemoteToXml(p.extraRemotes[r], doc, e) | ||
| 138 | for c in p.copyfiles: | ||
| 139 | ce = doc.createElement('copyfile') | ||
| 140 | ce.setAttribute('src', c.src) | ||
| 141 | ce.setAttribute('dest', c.dest) | ||
| 142 | e.appendChild(ce) | ||
| 143 | |||
| 144 | doc.writexml(fd, '', ' ', '\n', 'UTF-8') | ||
| 145 | |||
| 76 | @property | 146 | @property |
| 77 | def projects(self): | 147 | def projects(self): |
| 78 | self._Load() | 148 | self._Load() |
| @@ -324,7 +394,7 @@ class Manifest(object): | |||
| 324 | if not self.IsMirror: | 394 | if not self.IsMirror: |
| 325 | # src is project relative; | 395 | # src is project relative; |
| 326 | # dest is relative to the top of the tree | 396 | # dest is relative to the top of the tree |
| 327 | project.AddCopyFile(src, os.path.join(self.topdir, dest)) | 397 | project.AddCopyFile(src, dest, os.path.join(self.topdir, dest)) |
| 328 | 398 | ||
| 329 | def _get_remote(self, node): | 399 | def _get_remote(self, node): |
| 330 | name = node.getAttribute('remote') | 400 | name = node.getAttribute('remote') |
| @@ -178,13 +178,15 @@ class DiffColoring(Coloring): | |||
| 178 | 178 | ||
| 179 | 179 | ||
| 180 | class _CopyFile: | 180 | class _CopyFile: |
| 181 | def __init__(self, src, dest): | 181 | def __init__(self, src, dest, abssrc, absdest): |
| 182 | self.src = src | 182 | self.src = src |
| 183 | self.dest = dest | 183 | self.dest = dest |
| 184 | self.abs_src = abssrc | ||
| 185 | self.abs_dest = absdest | ||
| 184 | 186 | ||
| 185 | def _Copy(self): | 187 | def _Copy(self): |
| 186 | src = self.src | 188 | src = self.abs_src |
| 187 | dest = self.dest | 189 | dest = self.abs_dest |
| 188 | # copy file if it does not exist or is out of date | 190 | # copy file if it does not exist or is out of date |
| 189 | if not os.path.exists(dest) or not filecmp.cmp(src, dest): | 191 | if not os.path.exists(dest) or not filecmp.cmp(src, dest): |
| 190 | try: | 192 | try: |
| @@ -691,11 +693,11 @@ class Project(object): | |||
| 691 | self._CopyFiles() | 693 | self._CopyFiles() |
| 692 | return True | 694 | return True |
| 693 | 695 | ||
| 694 | def AddCopyFile(self, src, dest): | 696 | def AddCopyFile(self, src, dest, absdest): |
| 695 | # dest should already be an absolute path, but src is project relative | 697 | # dest should already be an absolute path, but src is project relative |
| 696 | # make src an absolute path | 698 | # make src an absolute path |
| 697 | src = os.path.join(self.worktree, src) | 699 | abssrc = os.path.join(self.worktree, src) |
| 698 | self.copyfiles.append(_CopyFile(src, dest)) | 700 | self.copyfiles.append(_CopyFile(src, dest, abssrc, absdest)) |
| 699 | 701 | ||
| 700 | def DownloadPatchSet(self, change_id, patch_id): | 702 | def DownloadPatchSet(self, change_id, patch_id): |
| 701 | """Download a single patch set of a single change to FETCH_HEAD. | 703 | """Download a single patch set of a single change to FETCH_HEAD. |
diff --git a/subcmds/manifest.py b/subcmds/manifest.py index 69906faa..4374a9d0 100644 --- a/subcmds/manifest.py +++ b/subcmds/manifest.py | |||
| @@ -16,16 +16,21 @@ | |||
| 16 | import os | 16 | import os |
| 17 | import sys | 17 | import sys |
| 18 | 18 | ||
| 19 | from command import Command | 19 | from command import PagedCommand |
| 20 | 20 | ||
| 21 | class Manifest(Command): | 21 | class Manifest(PagedCommand): |
| 22 | common = False | 22 | common = False |
| 23 | helpSummary = "Manifest file" | 23 | helpSummary = "Manifest inspection utility" |
| 24 | helpUsage = """ | 24 | helpUsage = """ |
| 25 | %prog | 25 | %prog [-o {-|NAME.xml} [-r]] |
| 26 | """ | 26 | """ |
| 27 | _helpDescription = """ | 27 | _helpDescription = """ |
| 28 | The repo manifest file describes the projects mapped into the client. | 28 | |
| 29 | With the -o option, exports the current manifest for inspection. | ||
| 30 | The manifest and (if present) local_manifest.xml are combined | ||
| 31 | together to produce a single manifest file. This file can be stored | ||
| 32 | in a Git repository for use during future 'repo init' invocations. | ||
| 33 | |||
| 29 | """ | 34 | """ |
| 30 | 35 | ||
| 31 | @property | 36 | @property |
| @@ -39,6 +44,34 @@ The repo manifest file describes the projects mapped into the client. | |||
| 39 | fd.close() | 44 | fd.close() |
| 40 | return help | 45 | return help |
| 41 | 46 | ||
| 47 | def _Options(self, p): | ||
| 48 | p.add_option('-r', '--revision-as-HEAD', | ||
| 49 | dest='peg_rev', action='store_true', | ||
| 50 | help='Save revisions as current HEAD') | ||
| 51 | p.add_option('-o', '--output-file', | ||
| 52 | dest='output_file', | ||
| 53 | help='File to save the manifest to', | ||
| 54 | metavar='-|NAME.xml') | ||
| 55 | |||
| 56 | def _Output(self, opt): | ||
| 57 | if opt.output_file == '-': | ||
| 58 | fd = sys.stdout | ||
| 59 | else: | ||
| 60 | fd = open(opt.output_file, 'w') | ||
| 61 | self.manifest.Save(fd, | ||
| 62 | peg_rev = opt.peg_rev) | ||
| 63 | fd.close() | ||
| 64 | if opt.output_file != '-': | ||
| 65 | print >>sys.stderr, 'Saved manifest to %s' % opt.output_file | ||
| 66 | |||
| 42 | def Execute(self, opt, args): | 67 | def Execute(self, opt, args): |
| 68 | if args: | ||
| 69 | self.Usage() | ||
| 70 | |||
| 71 | if opt.output_file is not None: | ||
| 72 | self._Output(opt) | ||
| 73 | return | ||
| 74 | |||
| 75 | print >>sys.stderr, 'error: no operation to perform' | ||
| 43 | print >>sys.stderr, 'error: see repo help manifest' | 76 | print >>sys.stderr, 'error: see repo help manifest' |
| 44 | sys.exit(1) | 77 | sys.exit(1) |
