From 1927a524c798e99ce7b7a2847a68b6535cdf2c71 Mon Sep 17 00:00:00 2001 From: Santiago Perez De Rosso Date: Tue, 12 Jan 2016 23:08:57 -0500 Subject: [PATCH 1/6] now fuse works even when there's no common ancestor --- gitless/cli/gl_fuse.py | 21 +++++++++++++-------- gitless/core.py | 14 +++++--------- 2 files changed, 18 insertions(+), 17 deletions(-) diff --git a/gitless/cli/gl_fuse.py b/gitless/cli/gl_fuse.py index 8d9b60d..0039e09 100644 --- a/gitless/cli/gl_fuse.py +++ b/gitless/cli/gl_fuse.py @@ -40,7 +40,7 @@ def parser(subparsers, repo): fuse_parser.add_argument( '-ip', '--insertion-point', nargs='?', help=( - 'the commit where to put the divergent changes, dp for ' + 'the divergent changes will be inserted after the commit given, dp for ' 'divergent point is the default'), metavar='commit_id') fuse_parser.add_argument( '-a', '--abort', help='abort the fuse in progress', action='store_true') @@ -55,11 +55,21 @@ def main(args, repo): return True src_branch = helpers.get_branch_or_use_upstream(args.src, 'src', repo) - dp = repo.merge_base(current_b, src_branch) + + mb = repo.merge_base(current_b, src_branch) + if mb == src_branch.target: # the current branch is ahead or both branches are equal + pprint.err('No commits to fuse') + return False + + if (not args.insertion_point or args.insertion_point == 'dp' or + args.insertion_point == 'divergent-point'): + insertion_point = mb + else: + insertion_point = repo.revparse_single(args.insertion_point).id def valid_input(inp): walker = src_branch.history() - walker.hide(dp) + walker.hide(insertion_point) divergent_ids = frozenset(ci.id for ci in walker) errors_found = False @@ -81,11 +91,6 @@ def valid_input(inp): if not valid_input(exclude): return False - if (not args.insertion_point or args.insertion_point == 'dp' or - args.insertion_point == 'divergent-point'): - insertion_point = dp - else: - insertion_point = repo.revparse_single(args.insertion_point).id try: current_b.fuse( diff --git a/gitless/core.py b/gitless/core.py index f1fd97f..18954dd 100644 --- a/gitless/core.py +++ b/gitless/core.py @@ -862,14 +862,10 @@ def fuse(self, src, ip, only=None, exclude=None, op_cb=None): save_fn = op_cb.save if op_cb else None repo = self.gl_repo - mb = repo.merge_base(self, src) - if mb == src.target: # either self is ahead or both branches are equal - raise GlError('No commits to fuse') - - mb_to_src = src.history(reverse=True) - mb_to_src.hide(mb) - divergent_commits, fuse_commits = itertools.tee(mb_to_src, 2) + ip_to_src = src.history(reverse=True) + ip_to_src.hide(ip) + divergent_commits, fuse_commits = itertools.tee(ip_to_src, 2) if only: fuse_commits = (ci for ci in fuse_commits if ci.id in only) @@ -883,10 +879,10 @@ def fuse(self, src, ip, only=None, exclude=None, op_cb=None): # Figure out where to detach head # If the ip is not the mb, then we need to detach at the ip, because the # first div commit won't have the ip as its parent - # But, if the ip **is** the mb we can advance the head until the div + # But, if the ip **is** the merge base we can advance the head until the div # commits and the commits to fuse diverge detach_point = ip - if ip == mb: + if ip == repo.merge_base(self, src): for ci, fuse_ci in zip(divergent_commits, fuse_commits): if ci.id != fuse_ci.id: fuse_commits = itertools.chain([fuse_ci], fuse_commits) From c6d24b47bc94d3c52ef622a29ddcd10b64fe9bbc Mon Sep 17 00:00:00 2001 From: Santiago Perez De Rosso Date: Sat, 11 Jun 2016 21:05:17 -0400 Subject: [PATCH 2/6] tags --- gitless/cli/gl.py | 4 +- gitless/cli/gl_branch.py | 17 +---- gitless/cli/gl_tag.py | 128 ++++++++++++++++++++++++++++++++++++++ gitless/cli/helpers.py | 36 +++++++---- gitless/cli/pprint.py | 11 ++++ gitless/core.py | 128 ++++++++++++++++++++++++++++++++++++++ gitless/tests/test_e2e.py | 24 +++++++ 7 files changed, 319 insertions(+), 29 deletions(-) create mode 100644 gitless/cli/gl_tag.py diff --git a/gitless/cli/gl.py b/gitless/cli/gl.py index c3d7818..fe3a620 100644 --- a/gitless/cli/gl.py +++ b/gitless/cli/gl.py @@ -17,7 +17,7 @@ from gitless import core from . import ( - gl_track, gl_untrack, gl_status, gl_diff, gl_commit, gl_branch, + gl_track, gl_untrack, gl_status, gl_diff, gl_commit, gl_branch, gl_tag, gl_checkout, gl_merge, gl_resolve, gl_fuse, gl_remote, gl_publish, gl_switch, gl_init, gl_history) from . import pprint @@ -55,7 +55,7 @@ def main(): subparsers.required = True sub_cmds = [ - gl_track, gl_untrack, gl_status, gl_diff, gl_commit, gl_branch, + gl_track, gl_untrack, gl_status, gl_diff, gl_commit, gl_branch, gl_tag, gl_checkout, gl_merge, gl_resolve, gl_fuse, gl_remote, gl_publish, gl_switch, gl_init, gl_history] for sub_cmd in sub_cmds: diff --git a/gitless/cli/gl_branch.py b/gitless/cli/gl_branch.py index dabe71e..a484032 100644 --- a/gitless/cli/gl_branch.py +++ b/gitless/cli/gl_branch.py @@ -7,11 +7,6 @@ from __future__ import unicode_literals -try: - from StringIO import StringIO -except ImportError: - from io import StringIO - from clint.textui import colored from gitless import core @@ -93,14 +88,14 @@ def _do_list(repo, list_remote, v=False): pprint.item( '{0} {1} {2}'.format(current_str, color(b.branch_name), upstream_str)) if v: - pprint.item(' ➜ head is {0}'.format(_ci_str(b.head))) + pprint.item(' ➜ head is {0}'.format(pprint.commit_str(b.head))) if list_remote: for r in repo.remotes: for b in (r.lookup_branch(n) for n in r.listall_branches()): pprint.item(' {0}'.format(colored.yellow(str(b)))) if v: - pprint.item(' ➜ head is {0}'.format(_ci_str(b.head))) + pprint.item(' ➜ head is {0}'.format(pprint.commit_str(b.head))) def _do_create(create_b, dp, repo): @@ -190,11 +185,5 @@ def _do_set_head(commit_id, repo): curr_b = repo.current_branch curr_b.head = commit.id pprint.ok( - 'Head of current branch {0} is now {1}'.format(curr_b, _ci_str(commit))) + 'Head of current branch {0} is now {1}'.format(curr_b, pprint.commit_str(commit))) return True - - -def _ci_str(ci): - ci_str = StringIO() - pprint.commit(ci, compact=True, stream=ci_str.write) - return ci_str.getvalue().strip() diff --git a/gitless/cli/gl_tag.py b/gitless/cli/gl_tag.py new file mode 100644 index 0000000..c7a92fa --- /dev/null +++ b/gitless/cli/gl_tag.py @@ -0,0 +1,128 @@ +# -*- coding: utf-8 -*- +# Gitless - a version control system built on top of Git. +# Licensed under GNU GPL v2. + +"""gl tag - List, create, edit or delete tags.""" + + +from __future__ import unicode_literals + +from gitless import core + +from . import helpers, pprint + + +def parser(subparsers, _): + """Adds the tag parser to the given subparsers object.""" + desc = 'list, create, or delete tags' + tag_parser = subparsers.add_parser( + 'tag', help=desc, description=desc.capitalize()) + tag_parser.add_argument( + '-r', '--remote', + help='list remote tags in addition to local tags', + action='store_true') + + tag_parser.add_argument( + '-c', '--create', nargs='+', help='create tag(s)', dest='create_t', + metavar='tag') + tag_parser.add_argument( + '-ci', '--commit', + help='the commit to tag (only relevant if a new ' + 'tag is created; defaults to the HEAD commit)', default='HEAD', + dest='ci') + tag_parser.add_argument( + '-d', '--delete', nargs='+', help='delete tag(s)', dest='delete_t', + metavar='tag') + + tag_parser.set_defaults(func=main) + + +def main(args, repo): + ret = True + if args.create_t: + ret = _do_create(args.create_t, args.ci, repo) + elif args.delete_t: + ret = _do_delete(args.delete_t, repo) + else: + _do_list(repo, args.remote) + + return ret + + +def _do_list(repo, list_remote): + pprint.msg('List of tags:') + pprint.exp('do gl tag -c t to create tag t') + pprint.exp('do gl tag -d t to delete tag t') + pprint.blank() + + no_tags = True + for t in (repo.lookup_tag(n) for n in repo.listall_tags()): + pprint.item('{0} ➜ tags {1}'.format(t, pprint.commit_str(t.commit))) + no_tags = False + + if list_remote: + for r in repo.remotes: + for t in (r.lookup_tag(n) for n in r.listall_tags()): + pprint.item('{0} ➜ tags {1}'.format(t, pprint.commit_str(t.commit))) + no_tags = False + + if no_tags: + pprint.item('There are no tags to list') + + +def _do_create(create_t, dp, repo): + errors_found = False + + try: + target = repo.revparse_single(dp) + except KeyError: + raise ValueError('Invalid commit {0}'.format(dp)) + + for t_name in create_t: + r = repo + remote_str = '' + if '/' in t_name: # might want to create a remote tag + maybe_remote, maybe_remote_tag = t_name.split('/', 1) + if maybe_remote in repo.remotes: + r = repo.remotes[maybe_remote] + t_name = maybe_remote_tag + conf_msg = 'Tag {0} will be created in remote repository {1}'.format( + t_name, maybe_remote) + if not pprint.conf_dialog(conf_msg): + pprint.msg( + 'Aborted: creation of tag {0} in remote repository {1}'.format( + t_name, maybe_remote)) + continue + remote_str = ' in remote repository {0}'.format(maybe_remote) + try: + r.create_tag(t_name, target) + pprint.ok('Created new tag {0}{1}'.format(t_name, remote_str)) + except ValueError as e: + pprint.err(e) + errors_found = True + + return not errors_found + + +def _do_delete(delete_t, repo): + errors_found = False + + for t_name in delete_t: + try: + t = helpers.get_tag(t_name, repo) + + tag_str = 'Tag {0} will be removed'.format(t.tag_name) + remote_str = '' + if isinstance(t, core.RemoteTag): + remote_str = 'from remote repository {0}'.format(t.remote_name) + if not pprint.conf_dialog('{0} {1}'.format(tag_str, remote_str)): + pprint.msg('Aborted: removal of tag {0}'.format(t)) + continue + + t.delete() + pprint.ok('Tag {0} removed successfully'.format(t)) + except ValueError as e: + pprint.err(e) + errors_found = True + + return not errors_found diff --git a/gitless/cli/helpers.py b/gitless/cli/helpers.py index c2c01f9..5cfb480 100644 --- a/gitless/cli/helpers.py +++ b/gitless/cli/helpers.py @@ -18,25 +18,35 @@ def get_branch(branch_name, repo): - b = repo.lookup_branch(branch_name) - if not b: - if '/' not in branch_name: - raise ValueError('Branch "{0}" doesn\'t exist'.format(branch_name)) + return _get_ref("branch", branch_name, repo) - # It might be a remote branch - remote, remote_branch = branch_name.split('/', 1) + +def get_tag(tag_name, repo): + return _get_ref("tag", tag_name, repo) + + +def _get_ref(ref_type, ref_name, repo): + ref_type_cap = ref_type.capitalize() + r = getattr(repo, "lookup_" + ref_type)(ref_name) + if not r: + if '/' not in ref_name: + raise ValueError( + '{0} "{1}" doesn\'t exist'.format(ref_type_cap, ref_name)) + + # It might be a remote ref + remote, remote_ref = ref_name.split('/', 1) try: - r = repo.remotes[remote] + remote_repo = repo.remotes[remote] except KeyError: raise ValueError( 'Remote "{0}" doesn\'t exist, and there is no local ' - 'branch "{1}"'.format(remote, branch_name)) + '{1} "{2}"'.format(remote, ref_type_cap, ref_name)) - b = r.lookup_branch(remote_branch) - if not b: - raise ValueError('Branch "{0}" doesn\'t exist in remote "{1}"'.format( - remote_branch, remote)) - return b + r = getattr(remote_repo, "lookup_" + ref_type)(remote_ref) + if not r: + raise ValueError('{0} "{1}" doesn\'t exist in remote "{2}"'.format( + ref_type_cap, remote_ref, remote)) + return r def get_branch_or_use_upstream(branch_name, arg, repo): diff --git a/gitless/cli/pprint.py b/gitless/cli/pprint.py index a42cd44..d0ff6d2 100644 --- a/gitless/cli/pprint.py +++ b/gitless/cli/pprint.py @@ -7,6 +7,11 @@ from __future__ import unicode_literals +try: + from StringIO import StringIO +except ImportError: + from io import StringIO + from datetime import datetime, tzinfo, timedelta from locale import getpreferredencoding import re @@ -124,6 +129,12 @@ def get_user_input(text='> '): return input(text) +def commit_str(ci): + ci_str = StringIO() + commit(ci, compact=True, stream=ci_str.write) + return ci_str.getvalue().strip() + + def commit(ci, compact=False, stream=sys.stdout.write): merge_commit = len(ci.parent_ids) > 1 color = colored.magenta if merge_commit else colored.yellow diff --git a/gitless/core.py b/gitless/core.py index 18954dd..c7a0d0d 100644 --- a/gitless/core.py +++ b/gitless/core.py @@ -156,6 +156,41 @@ def _ref_target(self, ref): return self.git_repo.lookup_reference(ref).target + # Tag related methods + + def create_tag(self, name, commit): + tagger = self.git_repo.default_signature + try: + self.git_repo.create_tag( + name, commit.id, pygit2.GIT_OBJ_COMMIT, tagger, "") + return Tag(name, commit) + except ValueError as e: + raise ValueError( + str(e).replace('refs/tags/', '').replace('reference', 'tag')) + + def lookup_tag(self, tag_name): + try: + # We peel to get the commit pointed to by the tag (in the case of annotated + # tags, lookup_reference returns a tag object) + tag_target = self.git_repo.lookup_reference( + 'refs/tags/{0}'.format(tag_name)).peel() + if tag_target: + return Tag(tag_name, tag_target) + except KeyError: + pass + + def listall_tags(self): + """Returns a list with the names of all tags in this repository. + + Use lookup_tag to get the Tag object corresponding to eacn name. + """ + for ref in self.git_repo.listall_references(): + if ref.startswith('refs/tags/'): + if ref.endswith('^{}'): + continue + yield ref[10:] + + # Branch related methods @property @@ -405,6 +440,9 @@ def __init__(self, git_remote, gl_repo): self.name = self.git_remote.name self.url = self.git_remote.url + + # Branch related methods + def create_branch(self, name, head): if self.lookup_branch(name): raise GlError( @@ -442,6 +480,77 @@ def lookup_branch(self, branch_name): return RemoteBranch(git_branch, self.gl_repo) + # Tag related methods + + def create_tag(self, name, commit): + if self.lookup_tag(name): + raise GlError( + 'Tag {0} already exists in remote repository {1}'.format( + name, self.name)) + # We can't create a tag in a remote without creating a local one first. So + # we create a temporary local ref, make it point to the commit, and do the + # push + tmp_t = self.gl_repo.create_tag('gl_tmp_ref', commit) + try: + git.push(self.name, 'refs/tags/{0}:refs/tags/{1}'.format(tmp_t, name)) + return self.lookup_tag(name) + except ErrorReturnCode as e: + raise GlError(stderr(e)) + finally: + tmp_t.delete() + + def listall_tags(self): + """Return a list with the names of all tags in this repository. + + Use lookup_tag if you want to get the RemoteTag object corresponding + to each name. + """ + regex = re.compile(r'.*\trefs/tags/(.*)') + for head in stdout(git('ls-remote', '--tags', self.name)).splitlines(): + tag_name = regex.match(head).group(1) + if tag_name.endswith('^{}'): + continue + yield tag_name + + def lookup_tag(self, tag_name): + tag_info = stdout(git('ls-remote', '--tags', self.name, tag_name)) + if not tag_info: + return None + # The tag exists in the remote + git.fetch(self.git_remote.name, tag_name) + + regex = re.compile(r'(.*)\trefs/tags/.*') + commit_id = regex.match(tag_info).group(1) + commit = self.gl_repo.git_repo.get(commit_id).peel(pygit2.GIT_OBJ_COMMIT) + + return RemoteTag(self.git_remote.name, tag_name, commit) + + +class RemoteTag(object): + """A tag that lives on some remote repository. + + Attributes: + tag_name: the name of this tag: + remote_name: the name of the remote that represents the remote repository + where this tags lives. + commit: the commit this tag labels. + """ + + def __init__(self, remote_name, tag_name, commit): + self.remote_name = remote_name + self.tag_name = tag_name + self.commit = commit + + def delete(self): + try: + git.push(self.remote_name, ':{0}'.format(self.tag_name)) + except ErrorReturnCode as e: + raise GlError(stderr(e)) + + def __str__(self): + return self.remote_name + '/' + self.tag_name + + class RemoteBranch(object): """A branch that lives on some remote repository. @@ -1101,6 +1210,25 @@ def _check_is_current(self): 'Branch {0} is the current branch'.format(self.branch_name)) +class Tag(object): + """Static label for a commit. + + Attributes: + tag_name: the name of this tag. + commit: the commit this tag labels. + """ + + def __init__(self, tag_name, commit): + self.tag_name = tag_name + self.commit = commit + + def delete(self): + git.tag('-d', self.tag_name) + + def __str__(self): + return self.tag_name + + # Helpers for stashing def _stash(pattern): diff --git a/gitless/tests/test_e2e.py b/gitless/tests/test_e2e.py index 9b59a44..13ca5a4 100755 --- a/gitless/tests/test_e2e.py +++ b/gitless/tests/test_e2e.py @@ -287,6 +287,30 @@ def test_upstream(self): ErrorReturnCode, gl.branch, '-su', 'non-existent/non-existent') +class TestTag(TestEndToEnd): + + TAG_1 = 'tag1' + + def setUp(self): + super(TestTag, self).setUp() + utils.write_file('f') + gl.commit(o='f', m='commit') + + def test_create(self): + gl.tag(c=self.TAG_1) + self.assertRaises(ErrorReturnCode, gl.tag, c=self.TAG_1) + self.assertRaises(ErrorReturnCode, gl.tag, c='evil*named*tag') + if self.TAG_1 not in utils.stdout(gl.tag(_tty_out=False)): + self.fail() + + def test_remove(self): + gl.tag(c=self.TAG_1) + gl.tag(d=self.TAG_1, _in='n') + gl.tag(d=self.TAG_1, _in='y') + if self.TAG_1 in utils.stdout(gl.tag(_tty_out=False)): + self.fail() + + class TestDiffFile(TestEndToEnd): TRACKED_FP = 't_fp' From d180c41e5b41ce24e73655dad67235ca4534ad84 Mon Sep 17 00:00:00 2001 From: Santiago Perez De Rosso Date: Sun, 12 Jun 2016 17:22:43 -0400 Subject: [PATCH 3/6] partial commits --- gitless/cli/gl_commit.py | 35 +++++++++++++++++++++++++++++++++-- gitless/core.py | 18 ++++++++++++++---- 2 files changed, 47 insertions(+), 6 deletions(-) diff --git a/gitless/cli/gl_commit.py b/gitless/cli/gl_commit.py index 1bea01b..8769d66 100644 --- a/gitless/cli/gl_commit.py +++ b/gitless/cli/gl_commit.py @@ -7,6 +7,9 @@ from __future__ import unicode_literals +import subprocess +from sh import git + from gitless import core from . import commit_dialog @@ -24,6 +27,10 @@ def parser(subparsers, repo): 'flags')) commit_parser.add_argument( '-m', '--message', help='Commit message', dest='m') + commit_parser.add_argument( + '-p', '--partial', + help='Interactively select segments of files to commit', dest='p', + action='store_true') helpers.oei_flags(commit_parser, repo) commit_parser.set_defaults(func=main) @@ -36,13 +43,19 @@ def main(args, repo): pprint.err_exp('use gl track f if you want to track changes to file f') return False + curr_b = repo.current_branch + partials = None + if args.p: + partials = _do_partial_selection(commit_files, curr_b) + msg = args.m if args.m else commit_dialog.show(commit_files, repo) if not msg.strip(): + if partials: + git.reset('HEAD', partials) raise ValueError('Missing commit message') - curr_b = repo.current_branch _auto_track(commit_files, curr_b) - ci = curr_b.create_commit(commit_files, msg) + ci = curr_b.create_commit(commit_files, msg, partials=partials) pprint.ok('Commit succeeded') pprint.blank() @@ -56,6 +69,24 @@ def main(args, repo): return True +def _do_partial_selection(files, curr_b): + partials = [] + for fp in files: + f_st = curr_b.status_file(fp) + if not f_st.exists_at_head: + pprint.warn('Can\'t select segments for new file {0}'.format(fp)) + continue + if not f_st.exists_in_wd: + pprint.warn('Can\'t select segments for deleted file {0}'.format(fp)) + continue + + subprocess.call(['git', 'add', '-p', fp]) + # TODO: check that at least one hunk was staged + partials.append(fp) + + return partials + + def _auto_track(files, curr_b): """Tracks those untracked files in the list.""" for fp in files: diff --git a/gitless/core.py b/gitless/core.py index c7a0d0d..4a7aa3e 100644 --- a/gitless/core.py +++ b/gitless/core.py @@ -1108,7 +1108,7 @@ def _safe_restore(self, msg_fn, restore_fn=None): 'branch') - def create_commit(self, files, msg, author=None): + def create_commit(self, files, msg, author=None, partials=None): """Record a new commit on this branch. Args: @@ -1116,6 +1116,7 @@ def create_commit(self, files, msg, author=None): msg: the commit message. author: the author of the commit (defaults to the default author according to the repository's configuration). + partials: list of files to commit partially. """ git_repo = self.gl_repo.git_repo if not author: @@ -1125,12 +1126,15 @@ def create_commit(self, files, msg, author=None): if index.conflicts: raise GlError('Unresolved conflicts') - # We replicate the behaviour of doing `git commit ...` # If file f is in the list of files to be committed => commit the working - # version and clear the staged version. + # version (or the staged version if f is in the list of partially committed + # files) and clear the staged version. # If file f is not in the list of files to be committed => leave its staged # version (if any) intact. + if partials is None: + partials = [] + def get_tree_and_update_index(): def update(): @@ -1139,12 +1143,15 @@ def update(): assert not os.path.isabs(f) if not os.path.exists(os.path.join(self.gl_repo.root, f)): index.remove(f) - else: + elif f not in partials: index.add(f) # Update index to how it should look like after the commit + partial_entries = {} with index: update() + for f in partials: + partial_entries[f] = index._git_index[f] # To create the commit tree with only the changes to the given files we: # (i) reset the index to HEAD, @@ -1153,6 +1160,9 @@ def update(): # (iv) discard the changes after being done. index.read_tree(git_repo.head.peel().tree) update() + for f, index_entry in partial_entries.iteritems(): + index.add(index_entry) + tree_oid = index.write_tree() index.read() # discard changes From 943b82b0be40553175d28a3f98c943f6ad8d222a Mon Sep 17 00:00:00 2001 From: Santiago Perez De Rosso Date: Sun, 12 Jun 2016 22:06:22 -0400 Subject: [PATCH 4/6] py 2/3 fix --- gitless/core.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gitless/core.py b/gitless/core.py index 4a7aa3e..b3d28ae 100644 --- a/gitless/core.py +++ b/gitless/core.py @@ -1160,8 +1160,8 @@ def update(): # (iv) discard the changes after being done. index.read_tree(git_repo.head.peel().tree) update() - for f, index_entry in partial_entries.iteritems(): - index.add(index_entry) + for f in partial_entries.keys(): + index.add(partial_entries[f]) tree_oid = index.write_tree() From d091b42040926f18f6d629ae09824b02f8306224 Mon Sep 17 00:00:00 2001 From: Santiago Perez De Rosso Date: Wed, 15 Jun 2016 13:33:50 -0400 Subject: [PATCH 5/6] fix --- gitless/core.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gitless/core.py b/gitless/core.py index b3d28ae..6ecc4eb 100644 --- a/gitless/core.py +++ b/gitless/core.py @@ -907,16 +907,16 @@ def merge(self, src, op_cb=None): except ErrorReturnCode as e: raise GlError(stdout(e) + stderr(e)) + self._state_cleanup() restore_fn = op_cb.restore_ok if op_cb else None self._safe_restore(_stash_msg_merge, restore_fn=restore_fn) - self._state_cleanup() def merge_continue(self, op_cb=None): if not self.merge_in_progress: raise GlError('No merge in progress, nothing to continue') + self._state_cleanup() restore_fn = op_cb.restore_ok if op_cb else None self._safe_restore(_stash_msg_merge, restore_fn=restore_fn) - self._state_cleanup() @property def merge_in_progress(self): From eaa55e620f1976d0db45021f091399b0eb77b973 Mon Sep 17 00:00:00 2001 From: Santiago Perez De Rosso Date: Wed, 15 Jun 2016 13:50:24 -0400 Subject: [PATCH 6/6] prep for v0.8.3 --- gitless/cli/gl.py | 2 +- setup.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/gitless/cli/gl.py b/gitless/cli/gl.py index fe3a620..b11b7f8 100644 --- a/gitless/cli/gl.py +++ b/gitless/cli/gl.py @@ -29,7 +29,7 @@ INTERNAL_ERROR = 3 NOT_IN_GL_REPO = 4 -VERSION = '0.8.2' +VERSION = '0.8.3' URL = 'http://gitless.com' diff --git a/setup.py b/setup.py index c2592e1..9d0b4e2 100755 --- a/setup.py +++ b/setup.py @@ -7,7 +7,7 @@ from setuptools import setup -VERSION = '0.8.2' +VERSION = '0.8.3' # Build helper