git-p4: support updating an existing shelved changelist

Adds new option "--update-shelve CHANGELIST" which updates an existing shelved changelist. The original changelist must have been created by the current user. This allows workflow something like: hack hack hack git commit git p4 submit --shelve $mail interested parties about shelved changelist make corrections git commit --amend git p4 submit --update-shelve $CHANGELIST $mail interested parties about shelved changelist etc Signed-off-by: Luke Diamand <luke@diamand.org> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Luke Diamand committed Dec 2, 2016 at 22:43 UTC 46c609e9ffdbf8d9aba096836386b57371ed16b8
3 files changed +71 -4
Documentation/git-p4.txt
+4
@@ -308,6 +308,10 @@ These options can be used to modify 'git p4 submit' behavior.
308 After creating each shelve, the relevant files are reverted/deleted.
309 If you have multiple commits pending multiple shelves will be created.
310
311 +--update-shelve CHANGELIST::
312 + Update an existing shelved changelist with this commit. Implies
313 + --shelve.
314 +
315 --conflict=(ask|skip|quit)::
316 Conflicts can occur when applying a commit to p4. When this
317 happens, the default behavior ("ask") is to prompt whether to
git-p4.py
+29 -4
@@ -262,6 +262,10 @@ def p4_revert(f):
262 def p4_reopen(type, f):
263 p4_system(["reopen", "-t", type, wildcard_encode(f)])
264
265 +def p4_reopen_in_change(changelist, files):
266 + cmd = ["reopen", "-c", str(changelist)] + files
267 + p4_system(cmd)
268 +
269 def p4_move(src, dest):
270 p4_system(["move", "-k", wildcard_encode(src), wildcard_encode(dest)])
271
@@ -1292,6 +1296,9 @@ class P4Submit(Command, P4UserMap):
1296 optparse.make_option("--shelve", dest="shelve", action="store_true",
1297 help="Shelve instead of submit. Shelved files are reverted, "
1298 "restoring the workspace to the state before the shelve"),
1299 + optparse.make_option("--update-shelve", dest="update_shelve", action="store", type="int",
1300 + metavar="CHANGELIST",
1301 + help="update an existing shelved changelist, implies --shelve")
1302 ]
1303 self.description = "Submit changes from git to the perforce depot."
1304 self.usage += " [name of git branch to submit into perforce depot]"
@@ -1300,6 +1307,7 @@ class P4Submit(Command, P4UserMap):
1307 self.preserveUser = gitConfigBool("git-p4.preserveUser")
1308 self.dry_run = False
1309 self.shelve = False
1310 + self.update_shelve = None
1311 self.prepare_p4_only = False
1312 self.conflict_behavior = None
1313 self.isWindows = (platform.system() == "Windows")
@@ -1468,7 +1476,7 @@ class P4Submit(Command, P4UserMap):
1476 return 1
1477 return 0
1478
1471 - def prepareSubmitTemplate(self):
1479 + def prepareSubmitTemplate(self, changelist=None):
1480 """Run "p4 change -o" to grab a change specification template.
1481 This does not use "p4 -G", as it is nice to keep the submission
1482 template in original order, since a human might edit it.
@@ -1480,7 +1488,11 @@ class P4Submit(Command, P4UserMap):
1488
1489 template = ""
1490 inFilesSection = False
1483 - for line in p4_read_pipe_lines(['change', '-o']):
1491 + args = ['change', '-o']
1492 + if changelist:
1493 + args.append(str(changelist))
1494 +
1495 + for line in p4_read_pipe_lines(args):
1496 if line.endswith("\r\n"):
1497 line = line[:-2] + "\n"
1498 if inFilesSection:
@@ -1579,11 +1591,14 @@ class P4Submit(Command, P4UserMap):
1591 editedFiles = set()
1592 pureRenameCopy = set()
1593 filesToChangeExecBit = {}
1594 + all_files = list()
1595
1596 for line in diff:
1597 diff = parseDiffTreeEntry(line)
1598 modifier = diff['status']
1599 path = diff['src']
1600 + all_files.append(path)
1601 +
1602 if modifier == "M":
1603 p4_edit(path)
1604 if isModeExecChanged(diff['src_mode'], diff['dst_mode']):
@@ -1709,6 +1724,10 @@ class P4Submit(Command, P4UserMap):
1724 mode = filesToChangeExecBit[f]
1725 setP4ExecBit(f, mode)
1726
1727 + if self.update_shelve:
1728 + print("all_files = %s" % str(all_files))
1729 + p4_reopen_in_change(self.update_shelve, all_files)
1730 +
1731 #
1732 # Build p4 change description, starting with the contents
1733 # of the git commit message.
@@ -1717,7 +1736,7 @@ class P4Submit(Command, P4UserMap):
1736 logMessage = logMessage.strip()
1737 (logMessage, jobs) = self.separate_jobs_from_description(logMessage)
1738
1720 - template = self.prepareSubmitTemplate()
1739 + template = self.prepareSubmitTemplate(self.update_shelve)
1740 submitTemplate = self.prepareLogMessage(template, logMessage, jobs)
1741
1742 if self.preserveUser:
@@ -1789,7 +1808,10 @@ class P4Submit(Command, P4UserMap):
1808 if self.isWindows:
1809 message = message.replace("\r\n", "\n")
1810 submitTemplate = message[:message.index(separatorLine)]
1792 - if self.shelve:
1811 +
1812 + if self.update_shelve:
1813 + p4_write_pipe(['shelve', '-r', '-i'], submitTemplate)
1814 + elif self.shelve:
1815 p4_write_pipe(['shelve', '-i'], submitTemplate)
1816 else:
1817 p4_write_pipe(['submit', '-i'], submitTemplate)
@@ -1915,6 +1937,9 @@ class P4Submit(Command, P4UserMap):
1937 if len(self.origin) == 0:
1938 self.origin = upstream
1939
1940 + if self.update_shelve:
1941 + self.shelve = True
1942 +
1943 if self.preserveUser:
1944 if not self.canChangeChangelists():
1945 die("Cannot preserve user names without p4 super-user or admin permissions")
t/t9807-git-p4-submit.sh
+38
@@ -444,6 +444,44 @@ test_expect_success 'submit --shelve' '
444 )
445 '
446
447 +# Update an existing shelved changelist
448 +
449 +test_expect_success 'submit --update-shelve' '
450 + test_when_finished cleanup_git &&
451 + git p4 clone --dest="$git" //depot &&
452 + (
453 + cd "$cli" &&
454 + p4 revert ... &&
455 + cd "$git" &&
456 + git config git-p4.skipSubmitEdit true &&
457 + test_commit "test-update-shelved-change" &&
458 + git p4 submit --origin=HEAD^ --shelve &&
459 +
460 + shelf_cl=$(p4 -G changes -s shelved -m 1 |\
461 + marshal_dump change) &&
462 + test -n $shelf_cl &&
463 + echo "updating shelved change list $shelf_cl" &&
464 +
465 + echo "updated-line" >>shelf.t &&
466 + echo added-file.t >added-file.t &&
467 + git add shelf.t added-file.t &&
468 + git rm -f test-update-shelved-change.t &&
469 + git commit --amend -C HEAD &&
470 + git show --stat HEAD &&
471 + git p4 submit -v --origin HEAD^ --update-shelve $shelf_cl &&
472 + echo "done git p4 submit"
473 + ) &&
474 + (
475 + cd "$cli" &&
476 + change=$(p4 -G changes -s shelved -m 1 //depot/... | \
477 + marshal_dump change) &&
478 + p4 unshelve -c $change -s $change &&
479 + grep -q updated-line shelf.t &&
480 + p4 describe -S $change | grep added-file.t &&
481 + test_path_is_missing test-update-shelved-change.t
482 + )
483 +'
484 +
485 test_expect_success 'kill p4d' '
486 kill_p4d
487 '