Perforce – creating and editing a change list

My goal is to automatically create a changelist. I do this by running though some edit commands and submitting the change list at the end of the code sequence.

I run through all my commands in this similar order:

//Open all files in folder for edit in default changelist
p4.run(("edit", Folder + "..."))

//Move all files from default changelist to new changelist
changespec = p4.fetch_change()
changespec["Description"] = "test"
p4.save_change(changespec)

//Get changelist number
ChangeListNum = p4.run(("changes", "-m1", Folder + "..."))[0]['change']

//Run checks on files before submitting
p4.run("reconcile", "-a", "-c", ChangeListNum, Folder + "...")
p4.run("resolve", "-at", "-c", ChangeListNum, Folder + "...")
p4.run("revert", "-a", "-c", ChangeListNum, Folder + "...")

//Submit change list
p4.run("submit", "-c", ChangeListNum, "-f", "revertunchanged")

Now, during my checks and submit, my logger reports this error:

“Change #CL_Number is already committed.”

I sure it has to do something with mixing the P4Python functions like p4.fetch_change() and p4.run(). I’m not sure how to resolve this issue, but below is one solution I tried.

I tried changing the block of code:

changespec = p4.fetch_change()
changespec["Description"] = "test"
self.p4.save_change(changespec)

to this:

p4.run("change", "-i", "<", "P4ChangeList.txt")

That command reads in the change list txt i made, and creates a new changelist with those parameters. However, it only works in the cmd and not in the python command.

Thank you for any help!

Answer

The problem with the script is that this command:

//Get changelist number
ChangeListNum = p4.run(("changes", "-m1", Folder + "..."))[0]['change']

will give you the latest submitted change, because you provided a filespec (meaning the output is limited to changelists with submitted revisions matching that specification).

Even leaving that aside, structuring the script this way leaves you vulnerable to a race condition where another user might create a changelist in between when you create yours and when you run that query. What you’d want to do instead would be to capture the changelist number at the time that you save it (another user won’t be allowed to “steal” your change number so this is 100% safe from that sort of race).

But leaving THAT aside, your script is making something very complicated out of something very simple, which is “submit the files I changed” — since the script doesn’t modify any files itself I assume you’ve already edited the files before running it. Throw the whole script out and replace it with this:

# Open all changed files in the default changelist.
p4.run_reconcile(Folder + "...")
# Submit the default changelist.
p4.run_submit("-d", "test")

and you’re done!