diff options
Diffstat (limited to 'subcmds/diffmanifests.py')
| -rw-r--r-- | subcmds/diffmanifests.py | 374 |
1 files changed, 212 insertions, 162 deletions
diff --git a/subcmds/diffmanifests.py b/subcmds/diffmanifests.py index 4f9f5b0f..b446dbd8 100644 --- a/subcmds/diffmanifests.py +++ b/subcmds/diffmanifests.py | |||
| @@ -18,24 +18,24 @@ from manifest_xml import RepoClient | |||
| 18 | 18 | ||
| 19 | 19 | ||
| 20 | class _Coloring(Coloring): | 20 | class _Coloring(Coloring): |
| 21 | def __init__(self, config): | 21 | def __init__(self, config): |
| 22 | Coloring.__init__(self, config, "status") | 22 | Coloring.__init__(self, config, "status") |
| 23 | 23 | ||
| 24 | 24 | ||
| 25 | class Diffmanifests(PagedCommand): | 25 | class Diffmanifests(PagedCommand): |
| 26 | """ A command to see logs in projects represented by manifests | 26 | """A command to see logs in projects represented by manifests |
| 27 | 27 | ||
| 28 | This is used to see deeper differences between manifests. Where a simple | 28 | This is used to see deeper differences between manifests. Where a simple |
| 29 | diff would only show a diff of sha1s for example, this command will display | 29 | diff would only show a diff of sha1s for example, this command will display |
| 30 | the logs of the project between both sha1s, allowing user to see diff at a | 30 | the logs of the project between both sha1s, allowing user to see diff at a |
| 31 | deeper level. | 31 | deeper level. |
| 32 | """ | 32 | """ |
| 33 | 33 | ||
| 34 | COMMON = True | 34 | COMMON = True |
| 35 | helpSummary = "Manifest diff utility" | 35 | helpSummary = "Manifest diff utility" |
| 36 | helpUsage = """%prog manifest1.xml [manifest2.xml] [options]""" | 36 | helpUsage = """%prog manifest1.xml [manifest2.xml] [options]""" |
| 37 | 37 | ||
| 38 | helpDescription = """ | 38 | helpDescription = """ |
| 39 | The %prog command shows differences between project revisions of manifest1 and | 39 | The %prog command shows differences between project revisions of manifest1 and |
| 40 | manifest2. if manifest2 is not specified, current manifest.xml will be used | 40 | manifest2. if manifest2 is not specified, current manifest.xml will be used |
| 41 | instead. Both absolute and relative paths may be used for manifests. Relative | 41 | instead. Both absolute and relative paths may be used for manifests. Relative |
| @@ -65,159 +65,209 @@ synced and their revisions won't be found. | |||
| 65 | 65 | ||
| 66 | """ | 66 | """ |
| 67 | 67 | ||
| 68 | def _Options(self, p): | 68 | def _Options(self, p): |
| 69 | p.add_option('--raw', | 69 | p.add_option( |
| 70 | dest='raw', action='store_true', | 70 | "--raw", dest="raw", action="store_true", help="display raw diff" |
| 71 | help='display raw diff') | 71 | ) |
| 72 | p.add_option('--no-color', | 72 | p.add_option( |
| 73 | dest='color', action='store_false', default=True, | 73 | "--no-color", |
| 74 | help='does not display the diff in color') | 74 | dest="color", |
| 75 | p.add_option('--pretty-format', | 75 | action="store_false", |
| 76 | dest='pretty_format', action='store', | 76 | default=True, |
| 77 | metavar='<FORMAT>', | 77 | help="does not display the diff in color", |
| 78 | help='print the log using a custom git pretty format string') | 78 | ) |
| 79 | 79 | p.add_option( | |
| 80 | def _printRawDiff(self, diff, pretty_format=None, local=False): | 80 | "--pretty-format", |
| 81 | _RelPath = lambda p: p.RelPath(local=local) | 81 | dest="pretty_format", |
| 82 | for project in diff['added']: | 82 | action="store", |
| 83 | self.printText("A %s %s" % (_RelPath(project), project.revisionExpr)) | 83 | metavar="<FORMAT>", |
| 84 | self.out.nl() | 84 | help="print the log using a custom git pretty format string", |
| 85 | 85 | ) | |
| 86 | for project in diff['removed']: | 86 | |
| 87 | self.printText("R %s %s" % (_RelPath(project), project.revisionExpr)) | 87 | def _printRawDiff(self, diff, pretty_format=None, local=False): |
| 88 | self.out.nl() | 88 | _RelPath = lambda p: p.RelPath(local=local) |
| 89 | 89 | for project in diff["added"]: | |
| 90 | for project, otherProject in diff['changed']: | 90 | self.printText( |
| 91 | self.printText("C %s %s %s" % (_RelPath(project), project.revisionExpr, | 91 | "A %s %s" % (_RelPath(project), project.revisionExpr) |
| 92 | otherProject.revisionExpr)) | 92 | ) |
| 93 | self.out.nl() | ||
| 94 | self._printLogs(project, otherProject, raw=True, color=False, pretty_format=pretty_format) | ||
| 95 | |||
| 96 | for project, otherProject in diff['unreachable']: | ||
| 97 | self.printText("U %s %s %s" % (_RelPath(project), project.revisionExpr, | ||
| 98 | otherProject.revisionExpr)) | ||
| 99 | self.out.nl() | ||
| 100 | |||
| 101 | def _printDiff(self, diff, color=True, pretty_format=None, local=False): | ||
| 102 | _RelPath = lambda p: p.RelPath(local=local) | ||
| 103 | if diff['added']: | ||
| 104 | self.out.nl() | ||
| 105 | self.printText('added projects : \n') | ||
| 106 | self.out.nl() | ||
| 107 | for project in diff['added']: | ||
| 108 | self.printProject('\t%s' % (_RelPath(project))) | ||
| 109 | self.printText(' at revision ') | ||
| 110 | self.printRevision(project.revisionExpr) | ||
| 111 | self.out.nl() | ||
| 112 | |||
| 113 | if diff['removed']: | ||
| 114 | self.out.nl() | ||
| 115 | self.printText('removed projects : \n') | ||
| 116 | self.out.nl() | ||
| 117 | for project in diff['removed']: | ||
| 118 | self.printProject('\t%s' % (_RelPath(project))) | ||
| 119 | self.printText(' at revision ') | ||
| 120 | self.printRevision(project.revisionExpr) | ||
| 121 | self.out.nl() | ||
| 122 | |||
| 123 | if diff['missing']: | ||
| 124 | self.out.nl() | ||
| 125 | self.printText('missing projects : \n') | ||
| 126 | self.out.nl() | ||
| 127 | for project in diff['missing']: | ||
| 128 | self.printProject('\t%s' % (_RelPath(project))) | ||
| 129 | self.printText(' at revision ') | ||
| 130 | self.printRevision(project.revisionExpr) | ||
| 131 | self.out.nl() | ||
| 132 | |||
| 133 | if diff['changed']: | ||
| 134 | self.out.nl() | ||
| 135 | self.printText('changed projects : \n') | ||
| 136 | self.out.nl() | ||
| 137 | for project, otherProject in diff['changed']: | ||
| 138 | self.printProject('\t%s' % (_RelPath(project))) | ||
| 139 | self.printText(' changed from ') | ||
| 140 | self.printRevision(project.revisionExpr) | ||
| 141 | self.printText(' to ') | ||
| 142 | self.printRevision(otherProject.revisionExpr) | ||
| 143 | self.out.nl() | ||
| 144 | self._printLogs(project, otherProject, raw=False, color=color, | ||
| 145 | pretty_format=pretty_format) | ||
| 146 | self.out.nl() | ||
| 147 | |||
| 148 | if diff['unreachable']: | ||
| 149 | self.out.nl() | ||
| 150 | self.printText('projects with unreachable revisions : \n') | ||
| 151 | self.out.nl() | ||
| 152 | for project, otherProject in diff['unreachable']: | ||
| 153 | self.printProject('\t%s ' % (_RelPath(project))) | ||
| 154 | self.printRevision(project.revisionExpr) | ||
| 155 | self.printText(' or ') | ||
| 156 | self.printRevision(otherProject.revisionExpr) | ||
| 157 | self.printText(' not found') | ||
| 158 | self.out.nl() | ||
| 159 | |||
| 160 | def _printLogs(self, project, otherProject, raw=False, color=True, | ||
| 161 | pretty_format=None): | ||
| 162 | |||
| 163 | logs = project.getAddedAndRemovedLogs(otherProject, | ||
| 164 | oneline=(pretty_format is None), | ||
| 165 | color=color, | ||
| 166 | pretty_format=pretty_format) | ||
| 167 | if logs['removed']: | ||
| 168 | removedLogs = logs['removed'].split('\n') | ||
| 169 | for log in removedLogs: | ||
| 170 | if log.strip(): | ||
| 171 | if raw: | ||
| 172 | self.printText(' R ' + log) | ||
| 173 | self.out.nl() | 93 | self.out.nl() |
| 174 | else: | 94 | |
| 175 | self.printRemoved('\t\t[-] ') | 95 | for project in diff["removed"]: |
| 176 | self.printText(log) | 96 | self.printText( |
| 97 | "R %s %s" % (_RelPath(project), project.revisionExpr) | ||
| 98 | ) | ||
| 99 | self.out.nl() | ||
| 100 | |||
| 101 | for project, otherProject in diff["changed"]: | ||
| 102 | self.printText( | ||
| 103 | "C %s %s %s" | ||
| 104 | % ( | ||
| 105 | _RelPath(project), | ||
| 106 | project.revisionExpr, | ||
| 107 | otherProject.revisionExpr, | ||
| 108 | ) | ||
| 109 | ) | ||
| 110 | self.out.nl() | ||
| 111 | self._printLogs( | ||
| 112 | project, | ||
| 113 | otherProject, | ||
| 114 | raw=True, | ||
| 115 | color=False, | ||
| 116 | pretty_format=pretty_format, | ||
| 117 | ) | ||
| 118 | |||
| 119 | for project, otherProject in diff["unreachable"]: | ||
| 120 | self.printText( | ||
| 121 | "U %s %s %s" | ||
| 122 | % ( | ||
| 123 | _RelPath(project), | ||
| 124 | project.revisionExpr, | ||
| 125 | otherProject.revisionExpr, | ||
| 126 | ) | ||
| 127 | ) | ||
| 128 | self.out.nl() | ||
| 129 | |||
| 130 | def _printDiff(self, diff, color=True, pretty_format=None, local=False): | ||
| 131 | _RelPath = lambda p: p.RelPath(local=local) | ||
| 132 | if diff["added"]: | ||
| 133 | self.out.nl() | ||
| 134 | self.printText("added projects : \n") | ||
| 177 | self.out.nl() | 135 | self.out.nl() |
| 136 | for project in diff["added"]: | ||
| 137 | self.printProject("\t%s" % (_RelPath(project))) | ||
| 138 | self.printText(" at revision ") | ||
| 139 | self.printRevision(project.revisionExpr) | ||
| 140 | self.out.nl() | ||
| 178 | 141 | ||
| 179 | if logs['added']: | 142 | if diff["removed"]: |
| 180 | addedLogs = logs['added'].split('\n') | ||
| 181 | for log in addedLogs: | ||
| 182 | if log.strip(): | ||
| 183 | if raw: | ||
| 184 | self.printText(' A ' + log) | ||
| 185 | self.out.nl() | 143 | self.out.nl() |
| 186 | else: | 144 | self.printText("removed projects : \n") |
| 187 | self.printAdded('\t\t[+] ') | ||
| 188 | self.printText(log) | ||
| 189 | self.out.nl() | 145 | self.out.nl() |
| 146 | for project in diff["removed"]: | ||
| 147 | self.printProject("\t%s" % (_RelPath(project))) | ||
| 148 | self.printText(" at revision ") | ||
| 149 | self.printRevision(project.revisionExpr) | ||
| 150 | self.out.nl() | ||
| 190 | 151 | ||
| 191 | def ValidateOptions(self, opt, args): | 152 | if diff["missing"]: |
| 192 | if not args or len(args) > 2: | 153 | self.out.nl() |
| 193 | self.OptionParser.error('missing manifests to diff') | 154 | self.printText("missing projects : \n") |
| 194 | if opt.this_manifest_only is False: | 155 | self.out.nl() |
| 195 | raise self.OptionParser.error( | 156 | for project in diff["missing"]: |
| 196 | '`diffmanifest` only supports the current tree') | 157 | self.printProject("\t%s" % (_RelPath(project))) |
| 197 | 158 | self.printText(" at revision ") | |
| 198 | def Execute(self, opt, args): | 159 | self.printRevision(project.revisionExpr) |
| 199 | self.out = _Coloring(self.client.globalConfig) | 160 | self.out.nl() |
| 200 | self.printText = self.out.nofmt_printer('text') | 161 | |
| 201 | if opt.color: | 162 | if diff["changed"]: |
| 202 | self.printProject = self.out.nofmt_printer('project', attr='bold') | 163 | self.out.nl() |
| 203 | self.printAdded = self.out.nofmt_printer('green', fg='green', attr='bold') | 164 | self.printText("changed projects : \n") |
| 204 | self.printRemoved = self.out.nofmt_printer('red', fg='red', attr='bold') | 165 | self.out.nl() |
| 205 | self.printRevision = self.out.nofmt_printer('revision', fg='yellow') | 166 | for project, otherProject in diff["changed"]: |
| 206 | else: | 167 | self.printProject("\t%s" % (_RelPath(project))) |
| 207 | self.printProject = self.printAdded = self.printRemoved = self.printRevision = self.printText | 168 | self.printText(" changed from ") |
| 208 | 169 | self.printRevision(project.revisionExpr) | |
| 209 | manifest1 = RepoClient(self.repodir) | 170 | self.printText(" to ") |
| 210 | manifest1.Override(args[0], load_local_manifests=False) | 171 | self.printRevision(otherProject.revisionExpr) |
| 211 | if len(args) == 1: | 172 | self.out.nl() |
| 212 | manifest2 = self.manifest | 173 | self._printLogs( |
| 213 | else: | 174 | project, |
| 214 | manifest2 = RepoClient(self.repodir) | 175 | otherProject, |
| 215 | manifest2.Override(args[1], load_local_manifests=False) | 176 | raw=False, |
| 216 | 177 | color=color, | |
| 217 | diff = manifest1.projectsDiff(manifest2) | 178 | pretty_format=pretty_format, |
| 218 | if opt.raw: | 179 | ) |
| 219 | self._printRawDiff(diff, pretty_format=opt.pretty_format, | 180 | self.out.nl() |
| 220 | local=opt.this_manifest_only) | 181 | |
| 221 | else: | 182 | if diff["unreachable"]: |
| 222 | self._printDiff(diff, color=opt.color, pretty_format=opt.pretty_format, | 183 | self.out.nl() |
| 223 | local=opt.this_manifest_only) | 184 | self.printText("projects with unreachable revisions : \n") |
| 185 | self.out.nl() | ||
| 186 | for project, otherProject in diff["unreachable"]: | ||
| 187 | self.printProject("\t%s " % (_RelPath(project))) | ||
| 188 | self.printRevision(project.revisionExpr) | ||
| 189 | self.printText(" or ") | ||
| 190 | self.printRevision(otherProject.revisionExpr) | ||
| 191 | self.printText(" not found") | ||
| 192 | self.out.nl() | ||
| 193 | |||
| 194 | def _printLogs( | ||
| 195 | self, project, otherProject, raw=False, color=True, pretty_format=None | ||
| 196 | ): | ||
| 197 | logs = project.getAddedAndRemovedLogs( | ||
| 198 | otherProject, | ||
| 199 | oneline=(pretty_format is None), | ||
| 200 | color=color, | ||
| 201 | pretty_format=pretty_format, | ||
| 202 | ) | ||
| 203 | if logs["removed"]: | ||
| 204 | removedLogs = logs["removed"].split("\n") | ||
| 205 | for log in removedLogs: | ||
| 206 | if log.strip(): | ||
| 207 | if raw: | ||
| 208 | self.printText(" R " + log) | ||
| 209 | self.out.nl() | ||
| 210 | else: | ||
| 211 | self.printRemoved("\t\t[-] ") | ||
| 212 | self.printText(log) | ||
| 213 | self.out.nl() | ||
| 214 | |||
| 215 | if logs["added"]: | ||
| 216 | addedLogs = logs["added"].split("\n") | ||
| 217 | for log in addedLogs: | ||
| 218 | if log.strip(): | ||
| 219 | if raw: | ||
| 220 | self.printText(" A " + log) | ||
| 221 | self.out.nl() | ||
| 222 | else: | ||
| 223 | self.printAdded("\t\t[+] ") | ||
| 224 | self.printText(log) | ||
| 225 | self.out.nl() | ||
| 226 | |||
| 227 | def ValidateOptions(self, opt, args): | ||
| 228 | if not args or len(args) > 2: | ||
| 229 | self.OptionParser.error("missing manifests to diff") | ||
| 230 | if opt.this_manifest_only is False: | ||
| 231 | raise self.OptionParser.error( | ||
| 232 | "`diffmanifest` only supports the current tree" | ||
| 233 | ) | ||
| 234 | |||
| 235 | def Execute(self, opt, args): | ||
| 236 | self.out = _Coloring(self.client.globalConfig) | ||
| 237 | self.printText = self.out.nofmt_printer("text") | ||
| 238 | if opt.color: | ||
| 239 | self.printProject = self.out.nofmt_printer("project", attr="bold") | ||
| 240 | self.printAdded = self.out.nofmt_printer( | ||
| 241 | "green", fg="green", attr="bold" | ||
| 242 | ) | ||
| 243 | self.printRemoved = self.out.nofmt_printer( | ||
| 244 | "red", fg="red", attr="bold" | ||
| 245 | ) | ||
| 246 | self.printRevision = self.out.nofmt_printer("revision", fg="yellow") | ||
| 247 | else: | ||
| 248 | self.printProject = ( | ||
| 249 | self.printAdded | ||
| 250 | ) = self.printRemoved = self.printRevision = self.printText | ||
| 251 | |||
| 252 | manifest1 = RepoClient(self.repodir) | ||
| 253 | manifest1.Override(args[0], load_local_manifests=False) | ||
| 254 | if len(args) == 1: | ||
| 255 | manifest2 = self.manifest | ||
| 256 | else: | ||
| 257 | manifest2 = RepoClient(self.repodir) | ||
| 258 | manifest2.Override(args[1], load_local_manifests=False) | ||
| 259 | |||
| 260 | diff = manifest1.projectsDiff(manifest2) | ||
| 261 | if opt.raw: | ||
| 262 | self._printRawDiff( | ||
| 263 | diff, | ||
| 264 | pretty_format=opt.pretty_format, | ||
| 265 | local=opt.this_manifest_only, | ||
| 266 | ) | ||
| 267 | else: | ||
| 268 | self._printDiff( | ||
| 269 | diff, | ||
| 270 | color=opt.color, | ||
| 271 | pretty_format=opt.pretty_format, | ||
| 272 | local=opt.this_manifest_only, | ||
| 273 | ) | ||
