On 13 May 2018 at 14:52, Merland Romain <merlorom@xxxxxxxx> wrote: > Hello Luke, > > Very interseting > This is indeed an option we are waiting since the introduction of option --shelve for git p4 submit > What I like most in your approach is the preservation of link to p4/master inducing small changes of git-p4 existing functions already heavily tested. > Also I like the dedicated branch you create, it is cleaner and then we can cherry-pick in other git branches. Thanks, I'd be interested to know how you get on with it! > We made some basic tries on our side, just adding an option --unshelve to P4Submit (for simplicity, but I like much more your P4Unshelve class) > and trying to use the diff of p4 to generate a patch when possible, then apply it in the current git branch on top of HEAD. > Here it is, hope it can help a bit. > Note it also uses p4 print -o for binary files. I did try something like this earlier this year (if you look in the archives you'll find it) but I found that it was getting quite complicated trying to construct a sensible looking patch file from the output of p4 describe. Better to let git's existing tools do that, as they're going to be better than any half-baked attempt I might manage in Python! Thanks! Luke > > diff --git a/git-p4.py b/git-p4.py > index f4a6f3b4c..b466b46e1 100755 > --- a/git-p4.py > +++ b/git-p4.py > @@ -1353,6 +1353,8 @@ class P4Submit(Command, P4UserMap): > metavar="CHANGELIST", > help="update an existing shelved changelist, implies --shelve, " > "repeat in-order for multiple shelved changelists"), > + optparse.make_option("--unshelve", dest="unshelve", > + help="unshelve speficied ChangeList into current BRANCH."), > optparse.make_option("--commit", dest="commit", metavar="COMMIT", > help="submit only the specified commit(s), one commit or xxx..xxx"), > optparse.make_option("--disable-rebase", dest="disable_rebase", action="store_true", > @@ -1367,6 +1369,7 @@ class P4Submit(Command, P4UserMap): > self.dry_run = False > self.shelve = False > self.update_shelve = list() > + self.unshelve = "" > self.commit = "" > self.disable_rebase = False > self.prepare_p4_only = False > @@ -2083,6 +2086,66 @@ class P4Submit(Command, P4UserMap): > if self.clientPath == "": > die("Error: Cannot locate perforce checkout of %s in client view" % self.depotPath) > > + # special case of unshelving > + # todo: put this code in a class like P4Sync or P4Rebase > + if self.unshelve != "": > + git_dir = os.getcwd() + '/' > + print "Importing shelved CL %s into current git branch %s" % (self.unshelve, self.master) > + description = p4_describe(self.unshelve) > + > + # get changed files > + files = p4CmdList(['files', "@=%s" % self.unshelve]) > + editedFiles = [] > + filesToAdd = [] > + filesToDelete = [] > + binaryFiles = [] > + something_to_commit = False > + for f in files: > + if not f["depotFile"].startswith(self.depotPath): > + print "WARNING: file %s not in this p4 depot - skipping" % f["depotFile"] > + continue > + > + elif f["action"] == 'delete': > + filesToDelete.append(f) > + something_to_commit = True > + elif f["action"] == 'add': > + filesToAdd.append(f) > + something_to_commit = True > + elif f["type"] == 'binary': > + binaryFiles.append(f) > + something_to_commit = True > + elif f["action"] == 'edit': > + editedFiles.append(f) > + something_to_commit = True > + > + f["clientFile"] = f["depotFile"].replace(self.depotPath,self.clientPath) > + f["gitFile"] = f["depotFile"].replace(self.depotPath,git_dir) > + > + if not something_to_commit: > + print "Nothing to commit. Exiting" > + return True > + > + # get the diff and copy to diff directory > + for f in editedFiles: > + p4diff = p4_read_pipe(['diff2', '-du', f["depotFile"]+'#'+f["rev"], f["depotFile"]+'@='+self.unshelve]) > + p4diff = "\n".join(p4diff.split("\n")[1:]) > + p4diff = '--- '+f["gitFile"]+'\n' + '+++ '+f["gitFile"]+'\n' + p4diff > + write_pipe(['patch', '-d/', '-p0'], p4diff) > + write_pipe(['git', 'add', '-f', f["gitFile"]], "") > + for f in filesToAdd: > + p4_write_pipe(['print', '-o', f["gitFile"], f["depotFile"]+'@='+self.unshelve], "") > + write_pipe(['git', 'add', '-f', f["gitFile"]], "") > + for f in filesToDelete: > + os.remove(f["gitFile"]) > + write_pipe(['git', 'rm', f["gitFile"]], "") > + for f in binaryFiles: > + p4_write_pipe(['print', '-o', f["gitFile"], f["depotFile"]+'@='+self.unshelve], "") > + write_pipe(['git', 'add', '-f', f["gitFile"]], "") > + > + # finalize: commit in git > + write_pipe(['git', 'commit', '-m', description["desc"]], "") > + return True > + > print "Perforce checkout for depot path %s located at %s" % (self.depotPath, self.clientPath) > self.oldWorkingDirectory = os.getcwd() > > Romain > > > > Le samedi 12 mai 2018 à 23:24:48 UTC+2, Luke Diamand <luke@xxxxxxxxxxx> a écrit : > > > > > > This can be used to "unshelve" a shelved P4 commit into > a git commit. > > For example: > > $ git p4 unshelve 12345 > > The resulting commit ends up in the branch: > refs/remotes/p4/unshelved/12345 > > If that branch already exists, it is renamed - for example > the above branch would be saved as p4/unshelved/12345.1. > > Caveat: > > The unshelving is done against the current "p4/master" branch; > git-p4 uses "p4 print" to get the file contents at the requested > revision, and then fast-import creates a commit relative to p4/master. > > Ideally what you would want is for fast-import to create the > commit based on the Perforce "revision" prior to the shelved commit, > but Perforce doesn't have such a concept - to do this, git-p4 > would need to figure out the revisions of the individual files > before the shelved changelist, and then construct a temporary > git branch which matched this. > > It's possible to do this, but doing so makes this change a lot more > complicated. > > This limitation means that if you unshelve a change where some > of the changed files were not based on p4/master, you will get > an amalgam of the change you wanted, and these other changes. > > The reference branch can be changed manually with the "--origin" > option. > > The change adds a new Unshelve command class. This just runs the > existing P4Sync code tweaked to handle a shelved changelist. > > Signed-off-by: Luke Diamand <luke@xxxxxxxxxxx>