Skip to content

Commit 858b13c

Browse files
committed
auto stash on merge
1 parent 682a057 commit 858b13c

File tree

6 files changed

+84
-39
lines changed

6 files changed

+84
-39
lines changed

gitless/cli/gl_commit.py

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -49,13 +49,9 @@ def main(args, repo):
4949
pprint.commit(ci)
5050

5151
if curr_b.fuse_in_progress:
52-
pprint.blank()
53-
try:
54-
curr_b.fuse_continue(fuse_cb=pprint.FUSE_CB)
55-
pprint.ok('Fuse succeeded')
56-
except core.ApplyFailedError as e:
57-
pprint.ok('Fuse succeeded')
58-
raise e
52+
_op_continue(curr_b.fuse_continue, 'Fuse')
53+
elif curr_b.merge_in_progress:
54+
_op_continue(curr_b.merge_continue, 'Merge')
5955

6056
return True
6157

@@ -66,3 +62,13 @@ def _auto_track(files, curr_b):
6662
f = curr_b.status_file(fp)
6763
if f.type == core.GL_STATUS_UNTRACKED:
6864
curr_b.track_file(f.fp)
65+
66+
67+
def _op_continue(op, fn):
68+
pprint.blank()
69+
try:
70+
op(op_cb=pprint.OP_CB)
71+
pprint.ok('{0} succeeded'.format(op))
72+
except core.ApplyFailedError as e:
73+
pprint.ok('{0} succeeded'.format(op))
74+
raise e

gitless/cli/gl_fuse.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ def parser(subparsers, repo):
5050
def main(args, repo):
5151
current_b = repo.current_branch
5252
if args.abort:
53-
current_b.abort_fuse(fuse_cb=pprint.FUSE_CB)
53+
current_b.abort_fuse(op_cb=pprint.OP_CB)
5454
pprint.ok('Fuse aborted successfully')
5555
return True
5656

@@ -90,7 +90,7 @@ def valid_input(inp):
9090
try:
9191
current_b.fuse(
9292
src_branch, insertion_point, only=only, exclude=exclude,
93-
fuse_cb=pprint.FUSE_CB)
93+
op_cb=pprint.OP_CB)
9494
pprint.ok('Fuse succeeded')
9595
except core.ApplyFailedError as e:
9696
pprint.ok('Fuse succeeded')

gitless/cli/gl_merge.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
from __future__ import unicode_literals
99

10+
from gitless import core
1011

1112
from . import helpers, pprint
1213

@@ -30,6 +31,11 @@ def main(args, repo):
3031
pprint.ok('Merge aborted successfully')
3132
return True
3233

33-
current_b.merge(helpers.get_branch_or_use_upstream(args.src, 'src', repo))
34-
pprint.ok('Merge succeeded')
34+
src_branch = helpers.get_branch_or_use_upstream(args.src, 'src', repo)
35+
try:
36+
current_b.merge(src_branch, op_cb=pprint.OP_CB)
37+
pprint.ok('Merge succeeded')
38+
except core.ApplyFailedError as e:
39+
pprint.ok('Merge succeeded')
40+
raise e
3541
return True

gitless/cli/pprint.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ def commit(ci, compact=False, stream=sys.stdout.write):
145145
with indent(4):
146146
puts(ci.message, stream=stream)
147147

148-
# Fuse Callbacks
148+
# Op Callbacks
149149

150150
def apply_ok(ci):
151151
ok('Insertion of {0} succeeded'.format(ci.id))
@@ -165,7 +165,7 @@ def save():
165165
def restore_ok():
166166
ok('Uncommitted changes applied successfully to the new head of the branch')
167167

168-
FUSE_CB = core.FuseCb(apply_ok, apply_err, save, restore_ok)
168+
OP_CB = core.OpCb(apply_ok, apply_err, save, restore_ok)
169169

170170

171171
class FixedOffset(tzinfo):

gitless/core.py

Lines changed: 44 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -776,7 +776,7 @@ def diff_file(self, path):
776776

777777
# Merge related methods
778778

779-
def merge(self, src):
779+
def merge(self, src, op_cb=None):
780780
"""Merges the divergent changes of the src branch onto this one."""
781781
self._check_is_current()
782782
self._check_op_not_in_progress()
@@ -787,7 +787,27 @@ def merge(self, src):
787787
try:
788788
git.merge(src, '--no-ff')
789789
except ErrorReturnCode as e:
790-
raise GlError(stdout(e) + stderr(e))
790+
err = stderr(e)
791+
if not 'stash' in err:
792+
raise GlError(stdout(e) + err)
793+
if op_cb and op_cb.save:
794+
op_cb.save()
795+
git.stash.save('--', _stash_msg_merge)
796+
try:
797+
git.merge(src, '--no-ff')
798+
except ErrorReturnCode as e:
799+
raise GlError(stdout(e) + stderr(e))
800+
801+
restore_fn = op_cb.restore_ok if op_cb else None
802+
self._safe_restore(_stash_msg_merge, restore_fn=restore_fn)
803+
self._state_cleanup()
804+
805+
def merge_continue(self, op_cb=None):
806+
if not self.merge_in_progress:
807+
raise GlError('No merge in progress, nothing to continue')
808+
restore_fn = op_cb.restore_ok if op_cb else None
809+
self._safe_restore(_stash_msg_merge, restore_fn=restore_fn)
810+
self._state_cleanup()
791811

792812
@property
793813
def merge_in_progress(self):
@@ -825,7 +845,7 @@ def _load_fuse_commits(self):
825845
yield git_repo[ci_id]
826846
os.remove(self._fuse_commits_fp)
827847

828-
def fuse(self, src, ip, only=None, exclude=None, fuse_cb=None):
848+
def fuse(self, src, ip, only=None, exclude=None, op_cb=None):
829849
"""Fuse the given commits onto this branch.
830850
831851
Args:
@@ -835,12 +855,12 @@ def fuse(self, src, ip, only=None, exclude=None, fuse_cb=None):
835855
divergent commits from self or the divergent point.
836856
only: ids of commits to use only.
837857
exclude: ids of commtis to exclude.
838-
fuse_cb: see FuseCb.
858+
op_cb: see OpCb.
839859
"""
840860
self._check_is_current()
841861
self._check_op_not_in_progress()
842862

843-
save_fn = fuse_cb.save if fuse_cb else None
863+
save_fn = op_cb.save if op_cb else None
844864
repo = self.gl_repo
845865
mb = repo.merge_base(self, src)
846866

@@ -872,16 +892,16 @@ def fuse(self, src, ip, only=None, exclude=None, fuse_cb=None):
872892
fuse_commits = itertools.chain([fuse_ci], fuse_commits)
873893
break
874894
detach_point = ci.id
875-
if fuse_cb and fuse_cb.apply_ok:
876-
fuse_cb.apply_ok(ci)
895+
if op_cb and op_cb.apply_ok:
896+
op_cb.apply_ok(ci)
877897

878898
after_commits = self.history(reverse=True)
879899
after_commits.hide(ip)
880900
commits = itertools.chain(fuse_commits, after_commits)
881901
commits, _commits = itertools.tee(commits, 2)
882902
if not any(_commits): # it's a ff
883903
self._safe_reset(detach_point, _stash_msg_fuse, save_fn=save_fn)
884-
restore_fn = fuse_cb.restore_ok if fuse_cb else None
904+
restore_fn = op_cb.restore_ok if op_cb else None
885905
self._safe_restore(_stash_msg_fuse, restore_fn=restore_fn)
886906
return
887907

@@ -897,29 +917,29 @@ def fuse(self, src, ip, only=None, exclude=None, fuse_cb=None):
897917
repo.git_repo.set_head(repo.git_repo.head.peel().id)
898918
self._safe_reset(detach_point, _stash_msg_fuse, save_fn=save_fn)
899919

900-
self._fuse(commits, fuse_cb=fuse_cb)
920+
self._fuse(commits, op_cb=op_cb)
901921

902-
def fuse_continue(self, fuse_cb=None):
922+
def fuse_continue(self, op_cb=None):
903923
if not self.fuse_in_progress:
904924
raise GlError('No fuse in progress, nothing to continue')
905925
commits = self._load_fuse_commits()
906-
self._fuse(commits, fuse_cb=fuse_cb)
926+
self._fuse(commits, op_cb=op_cb)
907927

908-
def _fuse(self, commits, fuse_cb=None):
928+
def _fuse(self, commits, op_cb=None):
909929
git_repo = self.gl_repo.git_repo
910930
committer = git_repo.default_signature
911931

912932
for ci in commits:
913933
git_repo.cherrypick(ci.id)
914934
index = self._index
915935
if index.conflicts:
916-
if fuse_cb and fuse_cb.apply_err:
917-
fuse_cb.apply_err(ci)
936+
if op_cb and op_cb.apply_err:
937+
op_cb.apply_err(ci)
918938
self._save_fuse_commits(commits)
919939
raise GlError('There are conflicts you need to resolve')
920940

921-
if fuse_cb and fuse_cb.apply_ok:
922-
fuse_cb.apply_ok(ci)
941+
if op_cb and op_cb.apply_ok:
942+
op_cb.apply_ok(ci)
923943
tree_oid = index.write_tree(git_repo)
924944
git_repo.create_commit(
925945
'HEAD', # the name of the reference to update
@@ -931,22 +951,22 @@ def _fuse(self, commits, fuse_cb=None):
931951
orig_branch_ref.set_target(git_repo.head.target)
932952
git_repo.set_head(orig_branch_ref.name)
933953
self._state_cleanup()
934-
restore_fn = fuse_cb.restore_ok if fuse_cb else None
954+
restore_fn = op_cb.restore_ok if op_cb else None
935955
self._safe_restore(_stash_msg_fuse, restore_fn=restore_fn)
936956

937957
@property
938958
def fuse_in_progress(self):
939959
return self.gl_repo._ref_exists('GL_FUSE_ORIG_HEAD')
940960

941-
def abort_fuse(self, fuse_cb=None):
961+
def abort_fuse(self, op_cb=None):
942962
if not self.fuse_in_progress:
943963
raise GlError('No fuse in progress, nothing to abort')
944964
git_repo = self.gl_repo.git_repo
945965
git_repo.set_head(git_repo.lookup_reference('GL_FUSE_ORIG_HEAD').target)
946966
git_repo.reset(git_repo.head.peel().hex, pygit2.GIT_RESET_HARD)
947967

948968
self._state_cleanup()
949-
restore_fn = fuse_cb.restore_ok if fuse_cb else None
969+
restore_fn = op_cb.restore_ok if op_cb else None
950970
self._safe_restore(_stash_msg_fuse, restore_fn=restore_fn)
951971

952972
def _state_cleanup(self):
@@ -1044,9 +1064,6 @@ def update():
10441064
msg, get_tree_and_update_index(), # the commit tree
10451065
parents)
10461066

1047-
if self.merge_in_progress:
1048-
self.gl_repo.git_repo.state_cleanup()
1049-
10501067
return self.gl_repo.git_repo[ci_oid]
10511068

10521069
def publish(self, branch):
@@ -1109,11 +1126,14 @@ def _stash_msg(name):
11091126
def _stash_msg_fuse(name):
11101127
return _stash_msg('fuse-{0}'.format(name))
11111128

1129+
def _stash_msg_merge(name):
1130+
return _stash_msg('merge-{0}'.format(name))
1131+
11121132

11131133
# Misc
11141134

1115-
FuseCb = collections.namedtuple(
1116-
'FuseCb', ['apply_ok', 'apply_err', 'save', 'restore_ok'])
1135+
OpCb = collections.namedtuple(
1136+
'OpCb', ['apply_ok', 'apply_err', 'save', 'restore_ok'])
11171137

11181138
def stdout(p):
11191139
return p.stdout.decode(ENCODING)

gitless/tests/test_e2e.py

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -353,15 +353,15 @@ def test_diff_non_ascii(self):
353353
self.assertEqual(out1, out2)
354354

355355

356-
class TestFuse(TestEndToEnd):
356+
class TestOp(TestEndToEnd):
357357

358358
COMMITS_NUMBER = 4
359359
OTHER = 'other'
360360
MASTER_FILE = 'master_file'
361361
OTHER_FILE = 'other_file'
362362

363363
def setUp(self):
364-
super(TestFuse, self).setUp()
364+
super(TestOp, self).setUp()
365365

366366
self.commits = {}
367367
def create_commits(branch_name, fp):
@@ -382,6 +382,9 @@ def create_commits(branch_name, fp):
382382
create_commits(self.OTHER, self.OTHER_FILE)
383383
gl.switch('master')
384384

385+
386+
class TestFuse(TestOp):
387+
385388
def __assert_history(self, expected):
386389
out = utils.stdout(gl.history(_tty_out=False))
387390
cids = list(reversed(re.findall(r'ci (.*) in (.*)', out, re.UNICODE)))
@@ -592,6 +595,16 @@ def test_uncommitted_tracked_changes_that_conflict_append(self):
592595
# self.assertTrue('failed to apply' in utils.stderr(e))
593596

594597

598+
class TestMerge(TestOp):
599+
600+
def test_uncommitted_changes(self):
601+
utils.write_file(self.MASTER_FILE, contents='uncommitted')
602+
utils.write_file('master_untracked', contents='uncommitted')
603+
gl.merge(self.OTHER)
604+
self.assertEqual('uncommitted', utils.read_file(self.MASTER_FILE))
605+
self.assertEqual('uncommitted', utils.read_file('master_untracked'))
606+
607+
595608
class TestPerformance(TestEndToEnd):
596609

597610
FPS_QTY = 10000

0 commit comments

Comments
 (0)