Merge ~nacc/git-ubuntu:gu-review into git-ubuntu:master
- Git
- lp:~nacc/git-ubuntu
- gu-review
- Merge into master
Status: | Merged | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Approved by: | Nish Aravamudan | ||||||||||||
Approved revision: | 5c40be68759223bb4cae3c4b2eada937f684af2d | ||||||||||||
Merged at revision: | a066105299c91a3aae098ea601eb82ddbc5529ca | ||||||||||||
Proposed branch: | ~nacc/git-ubuntu:gu-review | ||||||||||||
Merge into: | git-ubuntu:master | ||||||||||||
Prerequisite: | ~nacc/git-ubuntu:bugfixes-after-refactor | ||||||||||||
Diff against target: |
912 lines (+282/-77) 14 files modified
gitubuntu/__main__.py (+3/-1) gitubuntu/build.py (+14/-7) gitubuntu/buildsource.py (+1/-1) gitubuntu/clone.py (+8/-5) gitubuntu/importer.py (+34/-21) gitubuntu/importlocal.py (+8/-6) gitubuntu/importppa.py (+5/-3) gitubuntu/lint.py (+7/-5) gitubuntu/merge.py (+15/-11) gitubuntu/queue.py (+4/-2) gitubuntu/remote.py (+9/-3) gitubuntu/review.py (+156/-0) gitubuntu/submit.py (+12/-8) gitubuntu/tag.py (+6/-4) |
||||||||||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Server Team CI bot | continuous-integration | Approve | |
Andreas Hasenack | Approve | ||
Robie Basak | Pending | ||
Review via email: mp+330615@code.launchpad.net |
This proposal supersedes a proposal from 2017-09-08.
Commit message
Description of the change
This is probably not perfect, but it's basically (right now) just a wrapper around other commands, after the refactoring to call into them directly without the shell.
Bikesheddable.
Updated to reuse existing repo unless --clone is passed.
Robie Basak (racb) : Posted in a previous version of this proposal | # |
Server Team CI bot (server-team-bot) wrote : Posted in a previous version of this proposal | # |
Server Team CI bot (server-team-bot) wrote : Posted in a previous version of this proposal | # |
FAILED: Continuous integration, rev:ad8c802eddc
https:/
Executed test runs:
SUCCESS: Checkout
FAILED: Style Check
Click here to trigger a rebuild:
https:/
Server Team CI bot (server-team-bot) wrote : Posted in a previous version of this proposal | # |
FAILED: Continuous integration, rev:ad8c802eddc
https:/
Executed test runs:
SUCCESS: Checkout
SUCCESS: Style Check
SUCCESS: Unit Tests
FAILED: Integration Tests
Click here to trigger a rebuild:
https:/
Server Team CI bot (server-team-bot) wrote : Posted in a previous version of this proposal | # |
PASSED: Continuous integration, rev:d672a163d7e
https:/
Executed test runs:
SUCCESS: Checkout
SUCCESS: Style Check
SUCCESS: Unit Tests
SUCCESS: Integration Tests
IN_PROGRESS: Declarative: Post Actions
Click here to trigger a rebuild:
https:/
Server Team CI bot (server-team-bot) wrote : Posted in a previous version of this proposal | # |
PASSED: Continuous integration, rev:1b6612100ce
https:/
Executed test runs:
SUCCESS: Checkout
SUCCESS: Style Check
SUCCESS: Unit Tests
SUCCESS: Integration Tests
IN_PROGRESS: Declarative: Post Actions
Click here to trigger a rebuild:
https:/
Andreas Hasenack (ahasenack) wrote : Posted in a previous version of this proposal | # |
A few comments inline, just one needs-fixing really. The other one about making it work with an existing local repository is future work I think, for another branch.
There is no outstanding merge MP, so I tried running this review command against an open MP that is not a debian merge (cpaelzer's libvirt one) and also against an already-merged MP of mine (samba take 4), and got crashes in both cases. I understand this is somewhat work-in-progress, being the first new command to take advantage of the latest refactoring that is about to land. But I wonder: what do you think about having a way to hide these wip commands from --help?
Andreas Hasenack (ahasenack) wrote : | # |
Got an error feeding it itself :) :
$ bin/git-ubuntu review https:/
Traceback (most recent call last):
File "bin/git-ubuntu", line 22, in <module>
main()
File "/home/
args.func(args)
File "/home/
args.
File "/home/
idx = target_
ValueError: substring not found
At that point, target_url is:
(Pdb) p target_url
'https:/
Andreas Hasenack (ahasenack) wrote : | # |
Thanks for this. I have a few comments inline. Some can spawn new bugs and branches, others are suggestions/
Nish Aravamudan (nacc) wrote : | # |
On Tue, Sep 12, 2017 at 1:47 PM, Andreas Hasenack <email address hidden> wrote:
> Got an error feeding it itself :) :
> $ bin/git-ubuntu review https:/
> Traceback (most recent call last):
> File "bin/git-ubuntu", line 22, in <module>
> main()
> File "/home/
> args.func(args)
> File "/home/
> args.add_comment,
> File "/home/
> idx = target_
> ValueError: substring not found
>
> At that point, target_url is:
> (Pdb) p target_url
> 'https:/
I'll add more safeguarding on the input.
>
> Diff comments:
>
>> diff --git a/gitubuntu/
>> new file mode 100644
>> index 0000000..0acdbd3
>> --- /dev/null
>> +++ b/gitubuntu/
>> @@ -0,0 +1,140 @@
>> +import argparse
>> +from contextlib import redirect_stdout
>> +import io
>> +import logging
>> +import os
>> +import shutil
>> +import sys
>> +import tempfile
>> +import urllib.parse
>> +import gitubuntu.clone
>> +import gitubuntu.lint
>> +from gitubuntu.__main__ import top_level_defaults
>> +from gitubuntu.
>> + GitUbuntuReposi
>> + GitUbuntuReposi
>> +)
>> +from gitubuntu.
>> +
>> +
>> +def parse_args(
>> + kwargs = dict(
>> + description="Given a Launchpad MP URL, perform a review (EXPERIMENTAL)",
>> + formatter_
>> + epilog="An exit code of 0 indicates all checks passed",
>> + )
>> + if base_subparsers:
>> + kwargs["parents"] = base_subparsers
>> + if subparsers:
>> + parser = subparsers.
>> + parser.
>> + else:
>> + parser = argparse.
>> +
>> + parser.
>> + "url",
>> + type=str,
>> + help="Full URL of Launchpad Merge Proposal to review",
>> + )
>> + parser.
>> + '--clone',
>> + action=
>> + help="Create a new local repository by cloning, rather than "
>> + "using the repository at the current directory.",
>> + )
>> + parser.
>> + '--add-comment',
>> + action=
>> + help="Add a comment to the MP with the lint results. "
>> + "This may also change the review state",
>> + )
>> +
>> + if not subparsers:
>> + return parser.parse_args()
>> + return "review - %s" % kwargs[
>> +
>> +
>> +def cli_main(args):
>> + main(
>> + args.clone,
>> + args.url,
>> + args.add_comment,
>> + )
>> +
>> +def main(clone, url, add_comment):
>> + """Entry point to review
>> +
>> + Arguments:
>> + @clone: boolean to indicate a new repository should be cloned.
>
> "boolean to indicate *if* a new repos...
Nish Aravamudan (nacc) wrote : | # |
On Tue, Sep 12, 2017 at 2:20 PM, Andreas Hasenack <email address hidden> wrote:
> Review: Needs Fixing
>
> Thanks for this. I have a few comments inline. Some can spawn new bugs and branches, others are suggestions/
Ok.
> Diff comments:
>
>> diff --git a/gitubuntu/
>> new file mode 100644
>> index 0000000..0acdbd3
>> --- /dev/null
>> +++ b/gitubuntu/
>> @@ -0,0 +1,140 @@
>> +import argparse
>> +from contextlib import redirect_stdout
>> +import io
>> +import logging
>> +import os
>> +import shutil
>> +import sys
>> +import tempfile
>> +import urllib.parse
>> +import gitubuntu.clone
>> +import gitubuntu.lint
>> +from gitubuntu.__main__ import top_level_defaults
>> +from gitubuntu.
>> + GitUbuntuReposi
>> + GitUbuntuReposi
>> +)
>> +from gitubuntu.
>> +
>> +
>> +def parse_args(
>> + kwargs = dict(
>> + description="Given a Launchpad MP URL, perform a review (EXPERIMENTAL)",
>> + formatter_
>> + epilog="An exit code of 0 indicates all checks passed",
>> + )
>> + if base_subparsers:
>> + kwargs["parents"] = base_subparsers
>> + if subparsers:
>> + parser = subparsers.
>> + parser.
>> + else:
>> + parser = argparse.
>> +
>> + parser.
>> + "url",
>> + type=str,
>> + help="Full URL of Launchpad Merge Proposal to review",
>> + )
>> + parser.
>> + '--clone',
>> + action=
>> + help="Create a new local repository by cloning, rather than "
>> + "using the repository at the current directory.",
>> + )
>
> What do you think about --clone be the default? The most common scenario I think is to call the tool like this: "git ubuntu review <url>", which should just work. In other words, we would then have an option like --repository-path which you would give to point at an existing copy of the repository that contains the branch you want to review. This path would then be given to GitUbuntuReposi
I was asked for the opposite in the discussion with Robie in a different bug.
I think the most common case is already having a repository setup if
you are using `git ubuntu review` (because you earlier worked on it).
We'll fetch/update the local repo and then do a lint.
But that's bikesheddable and can be a feature request. I don't feel
strongly either way.
>> + parser.
>> + '--add-comment',
>> + action=
>> + help="Add a comment to the MP with the lint results. "
>> + "This may also change the review state",
>> + )
>> +
>> + if not subparsers:
>> + return parser.parse_args()
>> + return "review - %s" % kwargs[
>> +
>> +
>> +def cli_main(args):
>> + main(
>> + args.clone,
>> + args.url,
>> + args.add_comment,
>> + )
>> +
>> +def main(clone, url, add...
Nish Aravamudan (nacc) wrote : | # |
On Tue, Sep 12, 2017 at 2:45 PM, Nish Aravamudan
<email address hidden> wrote:
> On Tue, Sep 12, 2017 at 2:20 PM, Andreas Hasenack <email address hidden> wrote:
>> Review: Needs Fixing
>>
>> Thanks for this. I have a few comments inline. Some can spawn new bugs and branches, others are suggestions/
>
> Ok.
>
>> Diff comments:
>>
>>> diff --git a/gitubuntu/
>>> new file mode 100644
>>> index 0000000..0acdbd3
>>> --- /dev/null
>>> +++ b/gitubuntu/
>>> @@ -0,0 +1,140 @@
>>> +import argparse
>>> +from contextlib import redirect_stdout
>>> +import io
>>> +import logging
>>> +import os
>>> +import shutil
>>> +import sys
>>> +import tempfile
>>> +import urllib.parse
>>> +import gitubuntu.clone
>>> +import gitubuntu.lint
>>> +from gitubuntu.__main__ import top_level_defaults
>>> +from gitubuntu.
>>> + GitUbuntuReposi
>>> + GitUbuntuReposi
>>> +)
>>> +from gitubuntu.
>>> +
>>> +
>>> +def parse_args(
>>> + kwargs = dict(
>>> + description="Given a Launchpad MP URL, perform a review (EXPERIMENTAL)",
>>> + formatter_
>>> + epilog="An exit code of 0 indicates all checks passed",
>>> + )
>>> + if base_subparsers:
>>> + kwargs["parents"] = base_subparsers
>>> + if subparsers:
>>> + parser = subparsers.
>>> + parser.
>>> + else:
>>> + parser = argparse.
>>> +
>>> + parser.
>>> + "url",
>>> + type=str,
>>> + help="Full URL of Launchpad Merge Proposal to review",
>>> + )
>>> + parser.
>>> + '--clone',
>>> + action=
>>> + help="Create a new local repository by cloning, rather than "
>>> + "using the repository at the current directory.",
>>> + )
>>
>> What do you think about --clone be the default? The most common scenario I think is to call the tool like this: "git ubuntu review <url>", which should just work. In other words, we would then have an option like --repository-path which you would give to point at an existing copy of the repository that contains the branch you want to review. This path would then be given to GitUbuntuReposi
>
> I was asked for the opposite in the discussion with Robie in a different bug.
>
> I think the most common case is already having a repository setup if
> you are using `git ubuntu review` (because you earlier worked on it).
> We'll fetch/update the local repo and then do a lint.
>
> But that's bikesheddable and can be a feature request. I don't feel
> strongly either way.
>
>>> + parser.
>>> + '--add-comment',
>>> + action=
>>> + help="Add a comment to the MP with the lint results. "
>>> + "This may also change the review state",
>>> + )
>>> +
>>> + if not subparsers:
>>> + return parser.parse_args()
>>> + return "review - %s" % kwargs["desc...
Server Team CI bot (server-team-bot) wrote : | # |
FAILED: Continuous integration, rev:78e9c717fd0
https:/
Executed test runs:
SUCCESS: Checkout
SUCCESS: Style Check
FAILED: Unit Tests
Click here to trigger a rebuild:
https:/
Server Team CI bot (server-team-bot) wrote : | # |
FAILED: Continuous integration, rev:7b83eede9bd
https:/
Executed test runs:
SUCCESS: Checkout
SUCCESS: Style Check
FAILED: Unit Tests
Click here to trigger a rebuild:
https:/
Server Team CI bot (server-team-bot) wrote : | # |
FAILED: Continuous integration, rev:85d4ccab06e
https:/
Executed test runs:
SUCCESS: Checkout
FAILED: Style Check
Click here to trigger a rebuild:
https:/
Server Team CI bot (server-team-bot) wrote : | # |
FAILED: Continuous integration, rev:5ba6d95d2a8
https:/
Executed test runs:
SUCCESS: Checkout
SUCCESS: Style Check
SUCCESS: Unit Tests
FAILED: Integration Tests
Click here to trigger a rebuild:
https:/
Server Team CI bot (server-team-bot) wrote : | # |
PASSED: Continuous integration, rev:4ca0b55715e
https:/
Executed test runs:
SUCCESS: Checkout
SUCCESS: Style Check
SUCCESS: Unit Tests
SUCCESS: Integration Tests
IN_PROGRESS: Declarative: Post Actions
Click here to trigger a rebuild:
https:/
Andreas Hasenack (ahasenack) wrote : | # |
> >> Also, we should exit with e.code here, which is the linter exit status.
>
> Actually, hrm, I disagree with this last bit. The review subcommand
> succeeded even if the lint fails. That is, I'm not sure we would be
> able to distinguish a review iunternal error from a failed lint.
I raised this because you explicitly say this at the top;
epilog="An exit code of 0 indicates all checks passed",
Conversely, if a check failed, it should return non-zero.
Nish Aravamudan (nacc) wrote : | # |
On Wed, Sep 13, 2017 at 7:54 AM, Andreas Hasenack <email address hidden> wrote:
>> >> Also, we should exit with e.code here, which is the linter exit status.
>>
>> Actually, hrm, I disagree with this last bit. The review subcommand
>> succeeded even if the lint fails. That is, I'm not sure we would be
>> able to distinguish a review iunternal error from a failed lint.
>
> I raised this because you explicitly say this at the top;
>
> epilog="An exit code of 0 indicates all checks passed",
>
> Conversely, if a check failed, it should return non-zero.
C&P from lint.py :) Will drop.
- 1ff031b... by Nish Aravamudan
-
review: drop epilog from subparser
Will be squashed.
Server Team CI bot (server-team-bot) wrote : | # |
PASSED: Continuous integration, rev:1ff031bbc99
https:/
Executed test runs:
SUCCESS: Checkout
SUCCESS: Style Check
SUCCESS: Unit Tests
SUCCESS: Integration Tests
IN_PROGRESS: Declarative: Post Actions
Click here to trigger a rebuild:
https:/
- d1f6a0c... by Nish Aravamudan
-
review: return main from cli_main
Andreas Hasenack (ahasenack) wrote : | # |
We can drop the sys import now in gitubuntu/
$ pyflakes3 gitubuntu/|grep sys
gitubuntu/
gitubuntu/
gitubuntu/
gitubuntu/tag.py:4: 'sys' imported but unused
gitubuntu/
gitubuntu/
pyflakes3 actually shows many more unused modules, but let's leave that cleanup for another branch.
=1
Andreas Hasenack (ahasenack) wrote : | # |
er, I meant +1 :)
- 5c40be6... by Nish Aravamudan
-
review: drop unused sys
Server Team CI bot (server-team-bot) wrote : | # |
PASSED: Continuous integration, rev:d1f6a0c52e2
https:/
Executed test runs:
SUCCESS: Checkout
SUCCESS: Style Check
SUCCESS: Unit Tests
SUCCESS: Integration Tests
IN_PROGRESS: Declarative: Post Actions
Click here to trigger a rebuild:
https:/
Preview Diff
1 | diff --git a/gitubuntu/__main__.py b/gitubuntu/__main__.py |
2 | index 5c79265..78acc15 100644 |
3 | --- a/gitubuntu/__main__.py |
4 | +++ b/gitubuntu/__main__.py |
5 | @@ -69,6 +69,7 @@ def main(): |
6 | 'remote': 'gitubuntu.remote', |
7 | 'submit': 'gitubuntu.submit', |
8 | 'lint': 'gitubuntu.lint', |
9 | + 'review': 'gitubuntu.review', |
10 | } |
11 | |
12 | known_network_subcommands = { |
13 | @@ -81,6 +82,7 @@ def main(): |
14 | 'queue', |
15 | 'remote', |
16 | 'submit', |
17 | + 'review', |
18 | } |
19 | |
20 | parser = argparse.ArgumentParser( |
21 | @@ -223,7 +225,7 @@ def main(): |
22 | ) |
23 | sys.exit(1) |
24 | |
25 | - args.func(args) |
26 | + sys.exit(args.func(args)) |
27 | except KeyboardInterrupt: |
28 | sys.stderr.write('User abort\n') |
29 | sys.exit(130) |
30 | diff --git a/gitubuntu/build.py b/gitubuntu/build.py |
31 | index d3d292e..d78d5b5 100644 |
32 | --- a/gitubuntu/build.py |
33 | +++ b/gitubuntu/build.py |
34 | @@ -377,21 +377,23 @@ def check_repository(): |
35 | cp = run(['git', 'status', '--porcelain']) |
36 | except CalledProcessError: |
37 | logging.error('Is the current directory a git repository?') |
38 | - sys.exit(1) |
39 | + return False |
40 | |
41 | if len(cp.stdout) > 0: |
42 | logging.warning( |
43 | "Working tree is not clean. `git status` output follows." |
44 | ) |
45 | run(['git', 'status'], stdout=None) |
46 | - sys.exit(1) |
47 | + return False |
48 | |
49 | if not os.path.isfile('debian/changelog'): |
50 | logging.error( |
51 | "No debian/changelog found, is this a source " |
52 | "package repository? See `git ubuntu clone`." |
53 | ) |
54 | - sys.exit(1) |
55 | + return False |
56 | + |
57 | + return True |
58 | |
59 | |
60 | def main(search_list, changelog, rem_args): |
61 | @@ -400,10 +402,13 @@ def main(search_list, changelog, rem_args): |
62 | @param search_list: list of OrigSearchListEntry namedtuples |
63 | @param changelog: gitubuntu.git_repository.Changelog object for source package to build |
64 | @param rem_args: namespace object of remaining arguments to pass onto dpkg-buildpackage |
65 | + |
66 | + Returns 0 if the build succeeds, 1 otherwise. |
67 | """ |
68 | - check_repository() |
69 | + if not check_repository(): |
70 | + return 1 |
71 | |
72 | - fetch_orig_and_build(search_list, changelog, rem_args) |
73 | + return fetch_orig_and_build(search_list, changelog, rem_args) |
74 | |
75 | |
76 | def parse_args(subparsers=None, base_subparsers=None): |
77 | @@ -502,7 +507,7 @@ def cli_main(args): |
78 | native = is_native_package(changelog) |
79 | except NativenessMismatchError as e: |
80 | logging.error("%s" % e) |
81 | - sys.exit(1) |
82 | + return 1 |
83 | |
84 | if native: |
85 | # No orig tarball required |
86 | @@ -517,7 +522,7 @@ def cli_main(args): |
87 | orig_search_list = derive_orig_search_list_from_args(args) |
88 | |
89 | # See http://pad.ubuntu.com/KKB1kMR0JH for logic |
90 | - main(orig_search_list, changelog, rem_args) |
91 | + return main(orig_search_list, changelog, rem_args) |
92 | |
93 | |
94 | def derive_source_from_changelog(changelog): |
95 | @@ -589,6 +594,8 @@ def fetch_orig_and_build(orig_search_list, changelog, rem_args=[]): |
96 | "but none produced a successful build." |
97 | ) |
98 | |
99 | + return 0 |
100 | + |
101 | |
102 | class NativenessMismatchError(Exception): pass |
103 | |
104 | diff --git a/gitubuntu/buildsource.py b/gitubuntu/buildsource.py |
105 | index 1735129..6f02bf0 100644 |
106 | --- a/gitubuntu/buildsource.py |
107 | +++ b/gitubuntu/buildsource.py |
108 | @@ -63,4 +63,4 @@ def cli_main(args): |
109 | args.rem_args += ['-sa'] |
110 | if not args.sign: |
111 | args.rem_args += ['-us', '-uc'] |
112 | - build_cli_main(args) |
113 | + return build_cli_main(args) |
114 | diff --git a/gitubuntu/clone.py b/gitubuntu/clone.py |
115 | index c4d8dbd..ada365e 100644 |
116 | --- a/gitubuntu/clone.py |
117 | +++ b/gitubuntu/clone.py |
118 | @@ -50,7 +50,8 @@ def main( |
119 | If lp_user is None, value of `git config gitubuntu.lpuser` will be |
120 | used. |
121 | |
122 | - Returns the resulting GitUbuntuRepository object |
123 | + Returns the resulting GitUbuntuRepository object, if successful; |
124 | + None otherwise. |
125 | """ |
126 | directory = ( |
127 | os.path.abspath(directory) |
128 | @@ -59,7 +60,7 @@ def main( |
129 | ) |
130 | if os.path.isdir(directory): |
131 | logging.error('directory %s exists' % directory) |
132 | - sys.exit(1) |
133 | + return None |
134 | |
135 | local_repo = GitUbuntuRepository( |
136 | local_dir=directory, |
137 | @@ -82,7 +83,7 @@ def main( |
138 | package |
139 | ) |
140 | shutil.rmtree(local_repo.local_dir) |
141 | - raise |
142 | + return None |
143 | |
144 | try: |
145 | local_repo.add_lpuser_remote(pkgname=package) |
146 | @@ -157,12 +158,14 @@ def cli_main(args): |
147 | except AttributeError: |
148 | lp_user = None |
149 | |
150 | - main( |
151 | + if main( |
152 | package=args.package, |
153 | directory=args.directory, |
154 | lp_user=lp_user, |
155 | proto=args.proto, |
156 | - ) |
157 | + ) is not None: |
158 | + return 0 |
159 | + return 1 |
160 | |
161 | |
162 | # vi: ts=4 expandtab |
163 | diff --git a/gitubuntu/importer.py b/gitubuntu/importer.py |
164 | index 6311047..6c84e50 100644 |
165 | --- a/gitubuntu/importer.py |
166 | +++ b/gitubuntu/importer.py |
167 | @@ -78,6 +78,10 @@ class GitUbuntuImportOrigError(GitUbuntuImportError): |
168 | pass |
169 | |
170 | |
171 | +class ParentOverrideError(GitUbuntuImportError): |
172 | + pass |
173 | + |
174 | + |
175 | def dsc_to_tree_hash(repo, dsc_path): |
176 | '''Convert a dsc file into a git tree in the given repo |
177 | |
178 | @@ -179,6 +183,9 @@ def main( |
179 | |
180 | If dl_cache is None, CACHE_PATH in the local repository will be |
181 | used. |
182 | + |
183 | + Returns 0 on successful import (which includes non-fatal failures); |
184 | + 1 otherwise. |
185 | """ |
186 | if owner == 'usd-import-team': |
187 | namespace = 'importer' |
188 | @@ -327,7 +334,7 @@ def main( |
189 | if not history_found: |
190 | logging.error("No publication history for '%s' in debian or ubuntu. " |
191 | "Wrong source package name?", pkgname) |
192 | - sys.exit(1) |
193 | + return 1 |
194 | |
195 | if not skip_applied: |
196 | import_publishes( |
197 | @@ -400,6 +407,8 @@ def main( |
198 | time.sleep(retry_backoffs[i]) |
199 | lp_git_repo.lp_refresh() |
200 | |
201 | + return 0 |
202 | + |
203 | |
204 | def get_changelog_for_commit( |
205 | repo, |
206 | @@ -911,14 +920,13 @@ def override_parents(repo, spi, namespace): |
207 | 'specified in override file.' |
208 | ) |
209 | else: |
210 | - logging.error('Specified publish parent override ' |
211 | - '(%s) for version (%s) not found in tags. ' |
212 | - 'Unable to proceed.' % ( |
213 | - _PARENT_OVERRIDES[spi.version]['publish_parent'], |
214 | - spi.version |
215 | - ) |
216 | - ) |
217 | - sys.exit(1) |
218 | + raise ParentOverrideError( |
219 | + "Specified publish parent override (%s) for version (%s) " |
220 | + "not found in tags. Unable to proceed." % ( |
221 | + _PARENT_OVERRIDES[spi.version]['publish_parent'], |
222 | + spi.version |
223 | + ) |
224 | + ) |
225 | |
226 | unapplied_changelog_parent_tag = repo.get_import_tag( |
227 | _PARENT_OVERRIDES[spi.version]['changelog_parent'], |
228 | @@ -957,12 +965,13 @@ def override_parents(repo, spi, namespace): |
229 | 'in override file.' |
230 | ) |
231 | else: |
232 | - logging.error('Specified changelog parent override (%s) ' |
233 | - 'for version (%s) not found in tags. Unable to proceed.', |
234 | - _PARENT_OVERRIDES[spi.version]['changelog_parent'], |
235 | - spi.version |
236 | + raise ParentOverrideError( |
237 | + "Specified changelog parent override (%s) for version " |
238 | + "(%s) not found in tags. Unable to proceed." % ( |
239 | + _PARENT_OVERRIDES[spi.version]['changelog_parent'], |
240 | + spi.version, |
241 | + ) |
242 | ) |
243 | - sys.exit(1) |
244 | return ( |
245 | unapplied_publish_parent_commit, |
246 | unapplied_changelog_parent_commit, |
247 | @@ -1159,12 +1168,16 @@ def import_unapplied_spi(repo, spi, namespace, skip_orig, ubuntu_sinfo): |
248 | spi.version |
249 | ) |
250 | |
251 | - ( |
252 | - unapplied_publish_parent_commit, |
253 | - unapplied_changelog_parent_commit, |
254 | - _, |
255 | - _ |
256 | - ) = override_parents(repo, spi, namespace) |
257 | + try: |
258 | + ( |
259 | + unapplied_publish_parent_commit, |
260 | + unapplied_changelog_parent_commit, |
261 | + _, |
262 | + _ |
263 | + ) = override_parents(repo, spi, namespace) |
264 | + except ParentOverrideError as e: |
265 | + logging.error("%s" % e) |
266 | + return 1 |
267 | else: |
268 | # Get parent from publishing history (which is the last |
269 | # published version in the corresponding series) |
270 | @@ -1601,7 +1614,7 @@ def cli_main(args): |
271 | except AttributeError: |
272 | dl_cache = None |
273 | |
274 | - main( |
275 | + return main( |
276 | pkgname=args.package, |
277 | owner=args.lp_owner, |
278 | no_clean=no_clean, |
279 | diff --git a/gitubuntu/importlocal.py b/gitubuntu/importlocal.py |
280 | index c237551..1f5b51d 100644 |
281 | --- a/gitubuntu/importlocal.py |
282 | +++ b/gitubuntu/importlocal.py |
283 | @@ -43,7 +43,7 @@ def main( |
284 | if len(repo.raw_repo.status()) != 0: |
285 | logging.error('Working tree must be clean to continue.') |
286 | run(['git', 'status'], stdout=None) |
287 | - sys.exit(1) |
288 | + return 1 |
289 | |
290 | if os.path.exists(dsc_path): |
291 | dsc_path = os.path.abspath(dsc_path) |
292 | @@ -58,10 +58,10 @@ def main( |
293 | dscs = glob.glob(os.path.join(dsc_dir, '*.dsc')) |
294 | if len(dscs) == 0: |
295 | logging.error('Unable to obtain DSC file.') |
296 | - sys.exit(1) |
297 | + return 1 |
298 | if len(dscs) > 1: |
299 | logging.error('Multiple DSCs found in temporary directory.') |
300 | - sys.exit(1) |
301 | + return 1 |
302 | dsc_path = os.path.join(dsc_dir, dscs[0]) |
303 | os.chdir(oldcwd) |
304 | logging.debug('Importing DSC at local path %s', dsc_path) |
305 | @@ -71,7 +71,7 @@ def main( |
306 | 'Unable to verify orig tarball specified by DSC %s', |
307 | dsc_path, |
308 | ) |
309 | - sys.exit(1) |
310 | + return 1 |
311 | |
312 | pkgname = dsc['Source'] |
313 | |
314 | @@ -180,7 +180,7 @@ def main( |
315 | logging.error('Unable to import orig tarball for %s: %s', |
316 | changelog_version, e) |
317 | raise |
318 | - sys.exit(1) |
319 | + return 1 |
320 | |
321 | msg = ( |
322 | b'Import unapplied version %b\n\nImported using git-ubuntu-import.' % |
323 | @@ -283,6 +283,8 @@ def main( |
324 | |
325 | repo.garbage_collect() |
326 | |
327 | + return 0 |
328 | + |
329 | def parse_args(subparsers=None, base_subparsers=None): |
330 | kwargs = dict(description='Import a DSC file locally', |
331 | #usage='%(prog)s [options] -- ...', |
332 | @@ -325,7 +327,7 @@ def cli_main(args): |
333 | except AttributeError: |
334 | directory = None |
335 | |
336 | - main( |
337 | + return main( |
338 | directory, |
339 | args.namespace, |
340 | args.dsc, |
341 | diff --git a/gitubuntu/importppa.py b/gitubuntu/importppa.py |
342 | index da57f53..d5dcb96 100644 |
343 | --- a/gitubuntu/importppa.py |
344 | +++ b/gitubuntu/importppa.py |
345 | @@ -60,7 +60,7 @@ def main( |
346 | "Specified PPA (%s) is not in the format ppa:<name>", |
347 | ppa, |
348 | ) |
349 | - sys.exit(1) |
350 | + return 1 |
351 | # what other transformations? |
352 | namespace = ppa.replace(':', '_') |
353 | |
354 | @@ -148,7 +148,7 @@ def main( |
355 | pkgname, |
356 | ppa, |
357 | ) |
358 | - sys.exit(1) |
359 | + return 1 |
360 | |
361 | try: |
362 | for srcpkg_information in \ |
363 | @@ -179,6 +179,8 @@ def main( |
364 | |
365 | repo.garbage_collect() |
366 | |
367 | + return 0 |
368 | + |
369 | |
370 | def parse_args(subparsers=None, base_subparsers=None): |
371 | kwargs = dict(description='Update a launchpad git tree based upon ' |
372 | @@ -238,7 +240,7 @@ def cli_main(args): |
373 | except AttributeError: |
374 | dl_cache = None |
375 | |
376 | - main( |
377 | + return main( |
378 | args.ppa, |
379 | args.package, |
380 | directory, |
381 | diff --git a/gitubuntu/lint.py b/gitubuntu/lint.py |
382 | index ac503b9..2e03ff2 100644 |
383 | --- a/gitubuntu/lint.py |
384 | +++ b/gitubuntu/lint.py |
385 | @@ -203,7 +203,7 @@ def parse_args(subparsers=None, base_subparsers=None): |
386 | |
387 | def cli_main(args): |
388 | repo = GitUbuntuRepository(args.directory) |
389 | - do_lint( |
390 | + return do_lint( |
391 | repo, |
392 | args.commitish, |
393 | args.lint_namespace, |
394 | @@ -724,6 +724,8 @@ def do_lint( |
395 | branch. |
396 | |
397 | If lint_namespace is None, it will be derived from @commitish. |
398 | + |
399 | + Returns 0 if the lint succeeds; 1 otherwise. |
400 | """ |
401 | global _verbose |
402 | _verbose = verbose |
403 | @@ -736,7 +738,7 @@ def do_lint( |
404 | logging.error("%s is not a defined object in this git " |
405 | "repository: %s", commitish, e |
406 | ) |
407 | - sys.exit(1) |
408 | + return 1 |
409 | else: |
410 | commitish_obj = repo.raw_repo.head |
411 | if repo.raw_repo.head_is_detached: |
412 | @@ -750,7 +752,7 @@ def do_lint( |
413 | logging.error("HEAD is not detached, but unable to " |
414 | "determine what local branch HEAD points to." |
415 | ) |
416 | - sys.exit(1) |
417 | + return 1 |
418 | commitish_id = str(commitish_obj.id) |
419 | |
420 | if lint_namespace is None: |
421 | @@ -787,7 +789,7 @@ def do_lint( |
422 | |
423 | if lint_pass: |
424 | print("All lint checks passed") |
425 | - sys.exit(0) |
426 | + return 0 |
427 | else: |
428 | print("Some lint checks failed. Please investigate.") |
429 | - sys.exit(1) |
430 | + return 1 |
431 | diff --git a/gitubuntu/merge.py b/gitubuntu/merge.py |
432 | index cc16cc0..3baa748 100644 |
433 | --- a/gitubuntu/merge.py |
434 | +++ b/gitubuntu/merge.py |
435 | @@ -97,7 +97,7 @@ def parse_args(subparsers=None, base_subparsers=None): |
436 | return 'merge - %s' % kwargs['description'] |
437 | |
438 | def cli_main(args): |
439 | - main( |
440 | + return main( |
441 | directory=args.directory, |
442 | commitish=args.commitish, |
443 | onto=args.onto, |
444 | @@ -175,8 +175,9 @@ def do_start(repo, tag_prefix, commitish, merge_base_id, onto, force, tag_only): |
445 | do_tag(repo, tag_prefix, commitish, merge_base_id, onto, force) |
446 | if not tag_only: |
447 | do_reconstruct(repo, tag_prefix, commitish, merge_base_id, force) |
448 | + return 0 |
449 | except (TagException, ReconstructException): |
450 | - sys.exit(1) |
451 | + return 1 |
452 | |
453 | def do_merge_changelogs(repo, commitish, merge_base_id, onto): |
454 | # save merge_base_id:debian/changelog to tmp file |
455 | @@ -329,7 +330,7 @@ def do_finish(repo, tag_prefix, commitish, merge_base_id, onto, release, bug, fo |
456 | "start` first? (Pass -f to force the merge).", |
457 | msg |
458 | ) |
459 | - sys.exit(1) |
460 | + return 1 |
461 | |
462 | # 1) git merge-changelogs old/ubuntu old/debian new/debian |
463 | do_merge_changelogs(repo, commitish, merge_base_id, onto) |
464 | @@ -339,6 +340,7 @@ def do_finish(repo, tag_prefix, commitish, merge_base_id, onto, release, bug, fo |
465 | # (add flag to specify it?) |
466 | # 3) update-maintainer |
467 | do_update_maintainer(repo) |
468 | + return 0 |
469 | |
470 | |
471 | def main( |
472 | @@ -363,6 +365,8 @@ def main( |
473 | @bug: string bug number closed by this merge |
474 | @release: string Ubuntu release to target this merge to |
475 | @subcommand: string merge stage to run, one of 'start' or 'finish' |
476 | + |
477 | + Returns 0 if the subcommand completes successfully; 1 otherwise. |
478 | """ |
479 | repo = GitUbuntuRepository(directory) |
480 | tag_prefix = '' |
481 | @@ -376,7 +380,7 @@ def main( |
482 | "%s is not a defined object in this git repository.", |
483 | commitish |
484 | ) |
485 | - sys.exit(1) |
486 | + return 1 |
487 | |
488 | commitish_version, _ = repo.get_changelog_versions_from_treeish( |
489 | str(commitish_obj.id), |
490 | @@ -405,7 +409,7 @@ def main( |
491 | onto, |
492 | onto_version, |
493 | ) |
494 | - sys.exit(1) |
495 | + return 1 |
496 | except KeyError: |
497 | logging.info("%s is not a defined object in this git repository.", onto) |
498 | logging.info( |
499 | @@ -425,14 +429,14 @@ def main( |
500 | "Does it already exist (pass -f)?", |
501 | onto, |
502 | ) |
503 | - sys.exit(1) |
504 | + return 1 |
505 | onto_obj = repo.get_commitish(onto) |
506 | |
507 | cp = run(['git', 'status', '--porcelain']) |
508 | if len(cp.stdout) > 0: |
509 | logging.error('Working tree must be clean to continue:') |
510 | logging.error(decode_binary(cp.stdout)) |
511 | - sys.exit(1) |
512 | + return 1 |
513 | |
514 | merge_base_id = repo.raw_repo.merge_base( |
515 | onto_obj.id, |
516 | @@ -444,7 +448,7 @@ def main( |
517 | onto, |
518 | commitish, |
519 | ) |
520 | - sys.exit(1) |
521 | + return 1 |
522 | |
523 | if merge_base_id == onto_obj.id: |
524 | logging.error( |
525 | @@ -454,7 +458,7 @@ def main( |
526 | commitish, |
527 | onto, |
528 | ) |
529 | - sys.exit(1) |
530 | + return 1 |
531 | |
532 | merge_base_id = str(merge_base_id) |
533 | merge_base_version, _ = repo.get_changelog_versions_from_treeish( |
534 | @@ -462,7 +466,7 @@ def main( |
535 | ) |
536 | |
537 | if subcommand == 'start': |
538 | - do_start( |
539 | + return do_start( |
540 | repo, |
541 | tag_prefix, |
542 | commitish, |
543 | @@ -472,7 +476,7 @@ def main( |
544 | tag_only, |
545 | ) |
546 | elif subcommand == 'finish': |
547 | - do_finish( |
548 | + return do_finish( |
549 | repo, |
550 | tag_prefix, |
551 | commitish, |
552 | diff --git a/gitubuntu/queue.py b/gitubuntu/queue.py |
553 | index 0cd0b44..1ff4d12 100644 |
554 | --- a/gitubuntu/queue.py |
555 | +++ b/gitubuntu/queue.py |
556 | @@ -108,7 +108,7 @@ def parse_args(subparsers=None, base_subparsers=None): |
557 | return 'queue - %s' % kwargs['description'] |
558 | |
559 | def cli_main(args): |
560 | - main( |
561 | + return main( |
562 | args.directory, |
563 | args.subsubcommand, |
564 | args.fetch if args.subsubcommand == 'sync' else None, |
565 | @@ -328,7 +328,7 @@ def main( |
566 | repo.fetch_base_remotes() |
567 | except GitUbuntuRepositoryFetchError: |
568 | logging.error('No objects found in remote pkg') |
569 | - sys.exit(1) |
570 | + return 1 |
571 | |
572 | sync( |
573 | repo, |
574 | @@ -345,3 +345,5 @@ def main( |
575 | # elif args.subsubcommand == 'reject': |
576 | elif subsubcommand == 'clean': |
577 | clean(repo) |
578 | + |
579 | + return 0 |
580 | diff --git a/gitubuntu/remote.py b/gitubuntu/remote.py |
581 | index db42168..b874737 100644 |
582 | --- a/gitubuntu/remote.py |
583 | +++ b/gitubuntu/remote.py |
584 | @@ -63,7 +63,7 @@ def cli_main(args): |
585 | else: |
586 | directory = os.getcwd() |
587 | |
588 | - main( |
589 | + return main( |
590 | args.subsubcommand, |
591 | args.user, |
592 | args.package, |
593 | @@ -111,6 +111,8 @@ def do_add(repo, package, user, url=None, remote_name=None, no_fetch=False): |
594 | repo.raw_repo.remotes[remote_name].url, |
595 | ) |
596 | |
597 | + return 0 |
598 | + |
599 | def main( |
600 | subcommand, |
601 | user, |
602 | @@ -140,6 +142,8 @@ def main( |
603 | If directory is None, the current directory is used. |
604 | |
605 | If remote_name is None, the remote will be named @user. |
606 | + |
607 | + Returns 0 if the subcommand succeeded; 1 otherwise. |
608 | """ |
609 | if directory is None: |
610 | directory = os.path.abspath(os.getcwd()) |
611 | @@ -171,9 +175,11 @@ def main( |
612 | "Unable to determine source package name. Does " |
613 | "debian/changelog exist in the current branch?" |
614 | ) |
615 | - sys.exit(1) |
616 | + return 1 |
617 | |
618 | if subcommand == 'add': |
619 | - do_add(repo, package, user, url, remote_name, no_fetch) |
620 | + return do_add(repo, package, user, url, remote_name, no_fetch) |
621 | + |
622 | + return 1 |
623 | |
624 | # vi: ts=4 expandtab |
625 | diff --git a/gitubuntu/review.py b/gitubuntu/review.py |
626 | new file mode 100644 |
627 | index 0000000..8e252d5 |
628 | --- /dev/null |
629 | +++ b/gitubuntu/review.py |
630 | @@ -0,0 +1,156 @@ |
631 | +import argparse |
632 | +from contextlib import redirect_stdout |
633 | +import io |
634 | +import logging |
635 | +import os |
636 | +import shutil |
637 | +import tempfile |
638 | +import urllib.parse |
639 | +import gitubuntu.clone |
640 | +import gitubuntu.lint |
641 | +from gitubuntu.__main__ import top_level_defaults |
642 | +from gitubuntu.git_repository import ( |
643 | + GitUbuntuRepository, |
644 | + GitUbuntuRepositoryFetchError, |
645 | +) |
646 | +from gitubuntu.source_information import launchpad_login_auth |
647 | + |
648 | + |
649 | +def parse_args(subparsers=None, base_subparsers=None): |
650 | + kwargs = dict( |
651 | + description="Given a Launchpad MP URL, perform a review (EXPERIMENTAL)", |
652 | + formatter_class=argparse.RawTextHelpFormatter, |
653 | + ) |
654 | + if base_subparsers: |
655 | + kwargs["parents"] = base_subparsers |
656 | + if subparsers: |
657 | + parser = subparsers.add_parser("review", **kwargs) |
658 | + parser.set_defaults(func=cli_main) |
659 | + else: |
660 | + parser = argparse.ArgumentParser(**kwargs) |
661 | + |
662 | + parser.add_argument( |
663 | + "url", |
664 | + type=str, |
665 | + help="Full URL of Launchpad Merge Proposal to review", |
666 | + ) |
667 | + parser.add_argument( |
668 | + '--clone', |
669 | + action='store_true', |
670 | + help="Create a new local repository by cloning, rather than " |
671 | + "using the repository at the current directory.", |
672 | + ) |
673 | + parser.add_argument( |
674 | + '--add-comment', |
675 | + action='store_true', |
676 | + help="Add a comment to the MP with the lint results. " |
677 | + "This may also change the review state", |
678 | + ) |
679 | + |
680 | + if not subparsers: |
681 | + return parser.parse_args() |
682 | + return "review - %s" % kwargs["description"] |
683 | + |
684 | + |
685 | +def cli_main(args): |
686 | + return main( |
687 | + args.clone, |
688 | + args.url, |
689 | + args.add_comment, |
690 | + ) |
691 | + |
692 | +def main(clone, url, add_comment): |
693 | + """Entry point to review |
694 | + |
695 | + Arguments: |
696 | + @clone: if True, clone into a new local repository first. |
697 | + @url: string URL of MP to review |
698 | + @add_comment: if True, update the MP with the review results. |
699 | + |
700 | + Returns 0 if the review completed successfully (this does not |
701 | + indicate the review resulted in an approval of the MP); 1 otherwise. |
702 | + """ |
703 | + lp_path = urllib.parse.urlparse(url).path |
704 | + lp = launchpad_login_auth() |
705 | + mp = lp.load(lp_path) |
706 | + target_url = mp.target_git_repository.git_https_url |
707 | + target_branch = mp.target_git_path[len('refs/heads/'):] |
708 | + try: |
709 | + idx = target_url.index('~') |
710 | + target_user = target_url[idx+1:target_url.index('/', idx)] |
711 | + except ValueError: |
712 | + logging.error( |
713 | + "Unable to determine target user from %s", |
714 | + target_url, |
715 | + ) |
716 | + return 1 |
717 | + if target_user != 'usd-import-team': |
718 | + logging.error( |
719 | + "Performing arbitrary reviews is not yet supported (user %s " |
720 | + "specified).", |
721 | + target_user |
722 | + ) |
723 | + return 1 |
724 | + |
725 | + source_url = mp.source_git_repository.git_https_url |
726 | + source_branch = mp.source_git_path[len('refs/heads/'):] |
727 | + try: |
728 | + idx = source_url.index('~') |
729 | + source_user = source_url[idx+1:source_url.index('/', idx)] |
730 | + except ValueError: |
731 | + logging.error( |
732 | + "Unable to determine source user from %s", |
733 | + source_url, |
734 | + ) |
735 | + return 1 |
736 | + srcpkg = target_url.split('/')[-1] |
737 | + if clone: |
738 | + repo = gitubuntu.clone.main(package=srcpkg) |
739 | + else: |
740 | + repo = GitUbuntuRepository('.') |
741 | + try: |
742 | + repo.fetch_base_remotes() |
743 | + except GitUbuntuRepositoryFetchError: |
744 | + return 1 |
745 | + os.chdir(repo.local_dir) |
746 | + repo.add_remote( |
747 | + pkgname=srcpkg, |
748 | + repo_owner=source_user, |
749 | + remote_name=source_user, |
750 | + ) |
751 | + try: |
752 | + repo.fetch_remote(remote_name=source_user) |
753 | + except GitUbuntuRepositoryFetchError: |
754 | + return 1 |
755 | + |
756 | + logging.info( |
757 | + "Linting merge of %s/%s into pkg/%s" % ( |
758 | + source_user, |
759 | + source_branch, |
760 | + target_branch |
761 | + ) |
762 | + ) |
763 | + f = io.StringIO() |
764 | + with redirect_stdout(f): |
765 | + result = gitubuntu.lint.do_lint( |
766 | + repo=repo, |
767 | + commitish='%s/%s' % (source_user, source_branch), |
768 | + target_branch='pkg/%s' % target_branch, |
769 | + verbose=True, |
770 | + ) |
771 | + lint_out = f.getvalue() |
772 | + logging.info('git ubuntu lint result:') |
773 | + print(lint_out, end='') |
774 | + if add_comment: |
775 | + if result == 0: |
776 | + vote='Approve' |
777 | + else: |
778 | + vote='Needs Fixing' |
779 | + logging.info("Adding a %s comment to the MP", vote) |
780 | + mp.createComment( |
781 | + content=lint_out, |
782 | + vote=vote, |
783 | + subject="Automated lint result", |
784 | + ) |
785 | + |
786 | + return 0 |
787 | diff --git a/gitubuntu/submit.py b/gitubuntu/submit.py |
788 | index fb080f3..82267ad 100644 |
789 | --- a/gitubuntu/submit.py |
790 | +++ b/gitubuntu/submit.py |
791 | @@ -74,7 +74,7 @@ def cli_main(args): |
792 | except AttributeError: |
793 | user = None |
794 | |
795 | - main( |
796 | + return main( |
797 | directory=args.directory, |
798 | force=args.force, |
799 | target_user=args.target_user, |
800 | @@ -116,6 +116,8 @@ def main( |
801 | used. |
802 | |
803 | If branch is None, HEAD is used. |
804 | + |
805 | + Returns 0 if the MP was created successfully; 1 otherwise. |
806 | """ |
807 | repo = GitUbuntuRepository(directory, user, proto) |
808 | |
809 | @@ -129,7 +131,7 @@ def main( |
810 | else: |
811 | if repo.raw_repo.head_is_detached: |
812 | logging.error("Please create a local branch before submitting.") |
813 | - sys.exit(1) |
814 | + return 1 |
815 | source_branch = repo.raw_repo.head.name |
816 | commitish_string = 'HEAD' |
817 | |
818 | @@ -152,7 +154,7 @@ def main( |
819 | namespace, |
820 | ) |
821 | if len(target_head_string) == 0: |
822 | - sys.exit(1) |
823 | + return 1 |
824 | |
825 | logging.debug("target branch: %s", target_head_string) |
826 | |
827 | @@ -173,7 +175,7 @@ def main( |
828 | source_branch, |
829 | repo.lp_user, |
830 | ) |
831 | - sys.exit(1) |
832 | + return 1 |
833 | |
834 | lp = launchpad_login_auth() |
835 | |
836 | @@ -189,7 +191,7 @@ def main( |
837 | "Unable to find target repository (path=%s)", |
838 | path, |
839 | ) |
840 | - sys.exit(1) |
841 | + return 1 |
842 | |
843 | target_git_ref = target_git_repo.getRefByPath( |
844 | path='refs/heads/%s' % target_head_string |
845 | @@ -209,7 +211,7 @@ def main( |
846 | "Unable to find source repository (path=%s)", |
847 | path, |
848 | ) |
849 | - sys.exit(1) |
850 | + return 1 |
851 | |
852 | source_git_ref = source_git_repo.getRefByPath(path=source_branch) |
853 | if source_git_ref == None: |
854 | @@ -220,7 +222,7 @@ def main( |
855 | source_branch, |
856 | repo.lp_user, |
857 | ) |
858 | - sys.exit(1) |
859 | + return 1 |
860 | logging.debug("Source git ref: %s", source_git_ref) |
861 | |
862 | # create MP |
863 | @@ -228,7 +230,7 @@ def main( |
864 | mp = source_git_ref.createMergeProposal(merge_target=target_git_ref) |
865 | except BadRequest as e: |
866 | logging.error("Unable to create merge proposal: %s", e) |
867 | - sys.exit(1) |
868 | + return 1 |
869 | # only take unique reviewers |
870 | for potential_reviewer in set(reviewers): |
871 | try: |
872 | @@ -245,3 +247,5 @@ def main( |
873 | ) |
874 | print("Your merge proposal is now available at: %s" % mp.web_link) |
875 | print("If it looks ok, please move it to the 'Needs Review' state.") |
876 | + |
877 | + return 0 |
878 | diff --git a/gitubuntu/tag.py b/gitubuntu/tag.py |
879 | index 99027c3..b11a658 100644 |
880 | --- a/gitubuntu/tag.py |
881 | +++ b/gitubuntu/tag.py |
882 | @@ -58,7 +58,7 @@ def parse_args(subparsers=None, base_subparsers=None): |
883 | return 'tag - %s' % kwargs['description'] |
884 | |
885 | def cli_main(args): |
886 | - main( |
887 | + return main( |
888 | args.directory, |
889 | args.commitish, |
890 | args.force, |
891 | @@ -122,11 +122,11 @@ def main( |
892 | "%s is not a defined object in this git repository.", |
893 | commitish |
894 | ) |
895 | - sys.exit(1) |
896 | + return 1 |
897 | |
898 | if len(repo.raw_repo.status()) != 0: |
899 | logging.error('Working tree must be clean to continue.') |
900 | - sys.exit(1) |
901 | + return 1 |
902 | |
903 | version, _ = repo.get_changelog_versions_from_treeish(changelog_commitish) |
904 | dist = repo.get_changelog_distribution_from_treeish(changelog_commitish) |
905 | @@ -146,4 +146,6 @@ def main( |
906 | msg, |
907 | ) |
908 | except: |
909 | - sys.exit(1) |
910 | + return 1 |
911 | + |
912 | + return 0 |
FAILED: Continuous integration, rev:e0831bb2864 a48129d9143f1b0 e32831634101e8 /jenkins. ubuntu. com/server/ job/git- ubuntu- ci/26/
https:/
Executed test runs:
SUCCESS: Checkout
SUCCESS: Tests
FAILED: Build
Click here to trigger a rebuild: /jenkins. ubuntu. com/server/ job/git- ubuntu- ci/26/rebuild
https:/