diff --git a/functional-tests/040-test_simple_rebase.sh b/functional-tests/040-test_simple_rebase.sh index d152685..7010389 100755 --- a/functional-tests/040-test_simple_rebase.sh +++ b/functional-tests/040-test_simple_rebase.sh @@ -26,19 +26,21 @@ function test_simple_rebase() { log DEBUG "Creating a local patch" cat </dev/null || return 1 log DEBUG "Cherry picking upstream commits" diff --git a/git_upstream/commands/drop.py b/git_upstream/commands/drop.py index 4ac2579..dd34956 100644 --- a/git_upstream/commands/drop.py +++ b/git_upstream/commands/drop.py @@ -61,7 +61,8 @@ class Drop(LogDedentMixin, GitMixin): # test commit "id" presence self._commit = self.repo.commit(git_object) except BadObject: - raise DropError("Commit '%s' not found (or ambiguous)" % git_object) + raise DropError( + "Commit '%s' not found (or ambiguous)" % git_object) if not author: self._author = '%s <%s>' % (self.repo.git.config('user.name'), diff --git a/git_upstream/commands/import.py b/git_upstream/commands/import.py index c93669b..7a2c92b 100644 --- a/git_upstream/commands/import.py +++ b/git_upstream/commands/import.py @@ -43,7 +43,8 @@ class ImportUpstream(LogDedentMixin, GitMixin): def __init__(self, branch=None, upstream=None, import_branch=None, extra_branches=None, *args, **kwargs): - if not extra_branches: extra_branches = [] + if not extra_branches: + extra_branches = [] self._branch = branch self._upstream = upstream self._import_branch = import_branch @@ -72,7 +73,8 @@ class ImportUpstream(LogDedentMixin, GitMixin): invalid_ref = False for branch in branches: - if not any(head for head in self.repo.heads if head.name == branch): + if not any(head for head in self.repo.heads + if head.name == branch): msg = "Specified ref does not exist: '%s'" self.log.error(msg, branch) invalid_ref = True @@ -233,7 +235,8 @@ class ImportUpstream(LogDedentMixin, GitMixin): if len(commit.parents) < 2: ancestors.add(commit.hexsha) elif any(p.hexsha not in ancestors for p in commit.parents): - self.log.debug("Rebase upto commit SHA1: %s", commit.hexsha) + self.log.debug("Rebase upto commit SHA1: %s", + commit.hexsha) idx = idx + 1 break else: @@ -399,7 +402,8 @@ class ImportUpstream(LogDedentMixin, GitMixin): # the tree object id's match if self.git.rev_parse("HEAD^{tree}") != \ self.git.rev_parse("%s^{tree}" % self.import_branch): - raise ImportUpstreamError("Resulting tree does not match import") + raise ImportUpstreamError( + "Resulting tree does not match import") except (GitCommandError, ImportUpstreamError): self.log.error( """\ @@ -517,7 +521,8 @@ class LocateChangesWalk(LocateChangesStrategy): self.filters.append(ReverseCommitFilter()) self.filters.append(DroppedCommitFilter()) self.filters.append( - SupersededCommitFilter(self.search_ref, limit=self.searcher.commit)) + SupersededCommitFilter(self.search_ref, + limit=self.searcher.commit)) return super(LocateChangesWalk, self).filtered_iter() @@ -533,8 +538,8 @@ class LocateChangesWalk(LocateChangesStrategy): help='Force overwrite of existing import branch if it exists.') @subcommand.arg('--merge', dest='merge', required=False, action='store_true', default=True, - help='Merge the resulting import branch into the target branch ' - 'once complete') + help='Merge the resulting import branch into the target branch' + ' once complete') @subcommand.arg('--no-merge', dest='merge', required=False, action='store_false', help="Disable merge of the resulting import branch") @@ -571,7 +576,7 @@ def do_import(args): """ logger = log.get_logger('%s.%s' % (__name__, - inspect.stack()[0][0].f_code.co_name)) + inspect.stack()[0][0].f_code.co_name)) import_upstream = ImportUpstream(branch=args.branch, upstream=args.upstream_branch, diff --git a/git_upstream/lib/__init__.py b/git_upstream/lib/__init__.py index de23cc6..e69de29 100644 --- a/git_upstream/lib/__init__.py +++ b/git_upstream/lib/__init__.py @@ -1,18 +0,0 @@ -# -# Copyright (c) 2012, 2013, 2014 Hewlett-Packard Development Company, L.P. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -from git_upstream.lib import note diff --git a/git_upstream/lib/note.py b/git_upstream/lib/note.py index c778d69..f22b469 100644 --- a/git_upstream/lib/note.py +++ b/git_upstream/lib/note.py @@ -18,6 +18,7 @@ from git_upstream.errors import GitUpstreamError from git import base, GitCommandError + class NoteAlreadyExistsError(GitUpstreamError): """Exception thrown by note related commands""" pass @@ -44,6 +45,7 @@ def add_note(self, message, force=False, note_ref='refs/notes/commits'): else: raise e + def append_note(self, message, note_ref='refs/notes/commits'): """Add a note to an object :param message: note message @@ -51,6 +53,7 @@ def append_note(self, message, note_ref='refs/notes/commits'): """ self.repo.git.notes('--ref', note_ref, 'append', '-m', message, str(self)) + def note_message(self, note_ref='refs/notes/commits'): """ Return note message diff --git a/git_upstream/lib/pygitcompat.py b/git_upstream/lib/pygitcompat.py index 05e3014..cd79258 100644 --- a/git_upstream/lib/pygitcompat.py +++ b/git_upstream/lib/pygitcompat.py @@ -69,12 +69,13 @@ class GitUpstreamCompatCommit(Commit): message = '\n'.join(messages) - commits.append(GitUpstreamCompatCommit(repo, id=id, parents=parents, - tree=tree, author=author, - authored_date=authored_date, - committer=committer, - committed_date=committed_date, - message=message)) + commits.append(GitUpstreamCompatCommit( + repo, id=id, parents=parents, + tree=tree, author=author, + authored_date=authored_date, + committer=committer, + committed_date=committed_date, + message=message)) while lines: if not lines[0].strip(): diff --git a/git_upstream/lib/rebaseeditor.py b/git_upstream/lib/rebaseeditor.py index 923d0a4..2f448f2 100644 --- a/git_upstream/lib/rebaseeditor.py +++ b/git_upstream/lib/rebaseeditor.py @@ -21,7 +21,7 @@ from git_upstream.log import LogDedentMixin from subprocess import call import os -REBASE_EDITOR_SCRIPT = "rebase-editor.py" +REBASE_EDITOR_SCRIPT = "rebase-editor" # insure name of file will match any naming filters used by editors to # enable syntax highlighting diff --git a/git_upstream/lib/searchers.py b/git_upstream/lib/searchers.py index 3a14c13..f970e35 100644 --- a/git_upstream/lib/searchers.py +++ b/git_upstream/lib/searchers.py @@ -131,7 +131,8 @@ class UpstreamMergeBaseSearcher(LogDedentMixin, Searcher): def __init__(self, pattern="upstream/*", search_tags=False, remotes=None, *args, **kwargs): - if not remotes: remotes = [] + if not remotes: + remotes = [] self._pattern = pattern self._references = ["refs/heads/{0}".format(self.pattern)] @@ -160,7 +161,8 @@ class UpstreamMergeBaseSearcher(LogDedentMixin, Searcher): """ Searches the git history including local and remote branches, and tags if tag searching is enabled. References are included in the list to be - checked if they match the pattern that was specified in the constructor. + checked if they match the pattern that was specified in the + constructor. While 'git rev-list' supports a glob option to check all references, it isn't possible to anchor the pattern, so 'upstream/*' would match all of the following: @@ -184,9 +186,8 @@ class UpstreamMergeBaseSearcher(LogDedentMixin, Searcher): "Searching for most recent merge base with upstream branches") # process pattern given to get a list of refs to check - rev_list_args = self.git.for_each_ref(*self._references, - format="%(refname:short)" - ).splitlines() + rev_list_args = self.git.for_each_ref( + *self._references, format="%(refname:short)").splitlines() self.log.info( """\ Upstream refs: @@ -237,9 +238,9 @@ class UpstreamMergeBaseSearcher(LogDedentMixin, Searcher): revsions = self.git.rev_list(*rev_list_args).splitlines() # Running 'git merge-base' is relatively expensive to pruning the list - # of revs to search since it needs to construct and walk a large portion - # of the tree for each call. If the constructed graph was retained - # betweens we could likely remove much of the code above. + # of revs to search since it needs to construct and walk a large + # portion of the tree for each call. If the constructed graph was + # retained betweens we could likely remove much of the code above. self.log.info( """\ Running merge-base against each found upstream revision and target @@ -264,8 +265,8 @@ class UpstreamMergeBaseSearcher(LogDedentMixin, Searcher): git rev-list --topo-order --max-count=1 --no-walk \\ %s """, (" \\\n" + " " * 8).join(merge_bases)) - sha1 = self.git.rev_list(*merge_bases, topo_order=True, max_count=1, - no_walk=True) + sha1 = self.git.rev_list( + *merge_bases, topo_order=True, max_count=1, no_walk=True) # now that we have the sha1, make sure to save the commit object self.commit = self.repo.commit(sha1) self.log.debug("Most recent merge-base commit is: '%s'", @@ -418,7 +419,8 @@ class SupersededCommitFilter(LogDedentMixin, GitMixin, CommitFilter): raise ValueError( "Invalid object: no hexsha attribute for 'limit'") if not self.is_valid_commit(limit.hexsha): - raise ValueError("'limit' object does not contain a valid SHA1") + raise ValueError( + "'limit' object does not contain a valid SHA1") self.limit = limit self._regex = None @@ -609,7 +611,8 @@ class DiscardDuplicateGerritChangeId(LogDedentMixin, GitMixin, CommitFilter): raise ValueError( "Invalid object: no hexsha attribute for 'limit'") if not self.is_valid_commit(limit.hexsha): - raise ValueError("'limit' object does not contain a valid SHA1") + raise ValueError( + "'limit' object does not contain a valid SHA1") self.limit = limit self._regex = None diff --git a/git_upstream/log.py b/git_upstream/log.py index 27ad7e0..071db57 100644 --- a/git_upstream/log.py +++ b/git_upstream/log.py @@ -104,8 +104,8 @@ class DedentLoggerMeta(type): """ def __new__(cls, name, bases, dict): - # provide a more intelligent error instead of waiting for setattr/getattr - # adding of a wrapper function to fail + # provide a more intelligent error instead of waiting for + # setattr/getattr adding of a wrapper function to fail if logging.Logger not in bases: raise TypeError("%s not derived from logging.Logger" % name) diff --git a/git_upstream/scripts/rebase-editor.py b/git_upstream/rebase_editor.py similarity index 97% rename from git_upstream/scripts/rebase-editor.py rename to git_upstream/rebase_editor.py index f624d3c..bc098a8 100755 --- a/git_upstream/scripts/rebase-editor.py +++ b/git_upstream/rebase_editor.py @@ -58,15 +58,15 @@ def rebase_replace_insn(path, istream): print stripped -if __name__ == '__main__': +def main(): parser = ArgumentParser( description=__doc__.strip(), ) parser.add_argument('-v', '--verbose', action='store_true', default=False, help='Enable verbose mode') parser.add_argument('-i', '--interactive', action='store_true', - help='Enable interactive mode, where the user can edit ' - 'the list of commits before being applied') + help='Enable interactive mode, where the user can edit' + ' the list of commits before being applied') parser.add_argument('ifile', metavar='', help='File containing the new list of instructions to ' 'be placed into the rebase instructions file.') @@ -96,7 +96,7 @@ if __name__ == '__main__': # calling code should only override one of the two editor variables, # starting with the one with the highest precedence - editor=None + editor = None env = os.environ for var in ['GIT_SEQUENCE_EDITOR', 'GIT_EDITOR']: editor = env.get('GIT_UPSTREAM_' + var, None) @@ -121,3 +121,6 @@ if __name__ == '__main__': "environment to call as requested by the " "--interactive option.\n") sys.exit(2) + +if __name__ == '__main__': + return main() diff --git a/git_upstream/version.py b/git_upstream/version.py index f99336c..a579564 100644 --- a/git_upstream/version.py +++ b/git_upstream/version.py @@ -28,7 +28,8 @@ class CommandException(Exception): # following function is taken from git-review def run_command(cmd, status=False, env=None): - if not env: env = {} + if not env: + env = {} if VERBOSE: print(datetime.datetime.now(), "Running:", cmd) new_env = os.environ diff --git a/setup.cfg b/setup.cfg index d6a3a2e..46d2d12 100644 --- a/setup.cfg +++ b/setup.cfg @@ -31,3 +31,4 @@ packages = [entry_points] console_scripts = git-upstream = git_upstream.main:main + rebase-editor = git_upstream.rebase_editor:main diff --git a/tests/test_commands.py b/tests/test_commands.py index 0ad43a5..fed0c54 100644 --- a/tests/test_commands.py +++ b/tests/test_commands.py @@ -15,10 +15,11 @@ from argparse import ArgumentParser from git_upstream import commands as c + class TestGetSubcommands(testtools.TestCase): """Test case for get_subcommands function""" - _available_subcommands = ('import', 'supersede' ,'drop') + _available_subcommands = ('import', 'supersede', 'drop') def test_available_subcommands(self): """Test available subcommands""" diff --git a/tests/test_drop.py b/tests/test_drop.py index c82afd1..7eccff4 100644 --- a/tests/test_drop.py +++ b/tests/test_drop.py @@ -14,25 +14,26 @@ from git_upstream.commands import drop as d from git import repo as r from git import GitCommandError + class TestDrop(testtools.TestCase): """Test case for Drop class""" first_commit = "bd6b9eefe961abe8c15cb5dc6905b92e14714a4e" second_commit = "05fac847a5629e36050dcd69b9a782b2645d3cc7" invalid_commit = "this_is_an_invalid_commit" - author="Walter White " + author = "Walter White " note_ref = 'refs/notes/upstream-merge' def test_valid_parameters(self): """Test drop initialization and read properties""" - repo=r.Repo('.') - automatic_author='%s <%s>' % (repo.git.config('user.name'), - repo.git.config('user.email')) - t = d.Drop(git_object=TestDrop.first_commit) + repo = r.Repo('.') + automatic_author = '%s <%s>' % (repo.git.config('user.name'), + repo.git.config('user.email')) + t = d.Drop(git_object=TestDrop.first_commit) self.assertEquals(t.author, automatic_author) - t = d.Drop(git_object=TestDrop.first_commit, author=TestDrop.author) + t = d.Drop(git_object=TestDrop.first_commit, author=TestDrop.author) self.assertEquals(t.author, TestDrop.author) def test_invalid_commit(self): @@ -44,16 +45,16 @@ class TestDrop(testtools.TestCase): def test_mark(self): """Test drop mark""" - t = d.Drop(git_object=TestDrop.first_commit, author=TestDrop.author) + t = d.Drop(git_object=TestDrop.first_commit, author=TestDrop.author) repo = r.Repo('.') try: - # Older git versions don't support --ignore-missing so we need to - # catch GitCommandError exception - repo.git.notes('--ref', TestDrop.note_ref, 'remove', - TestDrop.first_commit) + # Older git versions don't support --ignore-missing so we need to + # catch GitCommandError exception + repo.git.notes('--ref', TestDrop.note_ref, 'remove', + TestDrop.first_commit) except GitCommandError: - pass + pass t.mark() diff --git a/tests/test_log.py b/tests/test_log.py index 5257e08..bc287d6 100644 --- a/tests/test_log.py +++ b/tests/test_log.py @@ -47,11 +47,12 @@ class TestGetIncrementLevel(testtools.TestCase): def _test_increment_by_x(self, increment=1): """Utility function that tests a given increment""" levels = len(self._levels) - for level_no in range(levels-increment): + for level_no in range(levels - increment): for level in self._levels[level_no]: result = l.get_increment_level(1, level) - self.assertEquals(self._levels[min(level_no+1, levels-1)][0].upper(), - result) + self.assertEquals( + self._levels[min(level_no + 1, levels - 1)][0].upper(), + result) def test_increments(self): """Test all possible increments for all possible default level""" diff --git a/tests/test_supersede.py b/tests/test_supersede.py index cfc4377..25301af 100644 --- a/tests/test_supersede.py +++ b/tests/test_supersede.py @@ -15,6 +15,7 @@ from git_upstream.commands import supersede as s from git import repo as r from git import GitCommandError + class TestSupersede(testtools.TestCase): """Test case for Supersede class""" @@ -32,9 +33,9 @@ class TestSupersede(testtools.TestCase): def test_valid_parameters(self): """Test supersede initialization and read properties""" - t = s.Supersede(git_object=TestSupersede.first_commit, - change_ids=TestSupersede.first_change_ids, - upstream_branch=TestSupersede.change_ids_branch) + t = s.Supersede(git_object=TestSupersede.first_commit, + change_ids=TestSupersede.first_change_ids, + upstream_branch=TestSupersede.change_ids_branch) self.assertEquals(str(t.commit), TestSupersede.first_commit) self.assertNotEqual(str(t.commit), TestSupersede.second_commit) @@ -54,9 +55,9 @@ class TestSupersede(testtools.TestCase): def test_multiple_change_id(self): """Test supersede initialization with multiple change ids""" - t = s.Supersede(git_object=TestSupersede.first_commit, - change_ids=TestSupersede.second_change_ids, - upstream_branch=TestSupersede.change_ids_branch) + t = s.Supersede(git_object=TestSupersede.first_commit, + change_ids=TestSupersede.second_change_ids, + upstream_branch=TestSupersede.change_ids_branch) self.assertEquals(str(t.commit), TestSupersede.first_commit) self.assertNotEqual(str(t.commit), TestSupersede.second_commit) @@ -88,17 +89,17 @@ class TestSupersede(testtools.TestCase): def test_mark(self): """Test Supersede mark""" - t = s.Supersede(git_object=TestSupersede.first_commit, - change_ids=TestSupersede.first_change_ids, - upstream_branch=TestSupersede.change_ids_branch) + t = s.Supersede(git_object=TestSupersede.first_commit, + change_ids=TestSupersede.first_change_ids, + upstream_branch=TestSupersede.change_ids_branch) repo = r.Repo('.') try: - # Older git versions don't support --ignore-missing - repo.git.notes('--ref', TestSupersede.note_ref, 'remove', - TestSupersede.first_commit) + # Older git versions don't support --ignore-missing + repo.git.notes('--ref', TestSupersede.note_ref, 'remove', + TestSupersede.first_commit) except GitCommandError: - pass + pass t.mark()