зеркало из https://github.com/microsoft/git.git
Merge branch 'pw/git-p4-jobs'
Teach "git p4" to notice "Jobs:" in the log message and relay it to Perforce to trigger its "jobs" support. # By Pete Wyckoff * pw/git-p4-jobs: git p4: notice Jobs lines in git commit messages git p4 test: refactor marshal_dump git p4: remove unused P4Submit interactive setting
This commit is contained in:
Коммит
7bdb74868c
58
git-p4.py
58
git-p4.py
|
@ -844,7 +844,6 @@ class P4Submit(Command, P4UserMap):
|
||||||
]
|
]
|
||||||
self.description = "Submit changes from git to the perforce depot."
|
self.description = "Submit changes from git to the perforce depot."
|
||||||
self.usage += " [name of git branch to submit into perforce depot]"
|
self.usage += " [name of git branch to submit into perforce depot]"
|
||||||
self.interactive = True
|
|
||||||
self.origin = ""
|
self.origin = ""
|
||||||
self.detectRenames = False
|
self.detectRenames = False
|
||||||
self.preserveUser = gitConfig("git-p4.preserveUser").lower() == "true"
|
self.preserveUser = gitConfig("git-p4.preserveUser").lower() == "true"
|
||||||
|
@ -855,9 +854,34 @@ class P4Submit(Command, P4UserMap):
|
||||||
if len(p4CmdList("opened ...")) > 0:
|
if len(p4CmdList("opened ...")) > 0:
|
||||||
die("You have files opened with perforce! Close them before starting the sync.")
|
die("You have files opened with perforce! Close them before starting the sync.")
|
||||||
|
|
||||||
# replaces everything between 'Description:' and the next P4 submit template field with the
|
def separate_jobs_from_description(self, message):
|
||||||
# commit message
|
"""Extract and return a possible Jobs field in the commit
|
||||||
def prepareLogMessage(self, template, message):
|
message. It goes into a separate section in the p4 change
|
||||||
|
specification.
|
||||||
|
|
||||||
|
A jobs line starts with "Jobs:" and looks like a new field
|
||||||
|
in a form. Values are white-space separated on the same
|
||||||
|
line or on following lines that start with a tab.
|
||||||
|
|
||||||
|
This does not parse and extract the full git commit message
|
||||||
|
like a p4 form. It just sees the Jobs: line as a marker
|
||||||
|
to pass everything from then on directly into the p4 form,
|
||||||
|
but outside the description section.
|
||||||
|
|
||||||
|
Return a tuple (stripped log message, jobs string)."""
|
||||||
|
|
||||||
|
m = re.search(r'^Jobs:', message, re.MULTILINE)
|
||||||
|
if m is None:
|
||||||
|
return (message, None)
|
||||||
|
|
||||||
|
jobtext = message[m.start():]
|
||||||
|
stripped_message = message[:m.start()].rstrip()
|
||||||
|
return (stripped_message, jobtext)
|
||||||
|
|
||||||
|
def prepareLogMessage(self, template, message, jobs):
|
||||||
|
"""Edits the template returned from "p4 change -o" to insert
|
||||||
|
the message in the Description field, and the jobs text in
|
||||||
|
the Jobs field."""
|
||||||
result = ""
|
result = ""
|
||||||
|
|
||||||
inDescriptionSection = False
|
inDescriptionSection = False
|
||||||
|
@ -870,6 +894,9 @@ class P4Submit(Command, P4UserMap):
|
||||||
if inDescriptionSection:
|
if inDescriptionSection:
|
||||||
if line.startswith("Files:") or line.startswith("Jobs:"):
|
if line.startswith("Files:") or line.startswith("Jobs:"):
|
||||||
inDescriptionSection = False
|
inDescriptionSection = False
|
||||||
|
# insert Jobs section
|
||||||
|
if jobs:
|
||||||
|
result += jobs + "\n"
|
||||||
else:
|
else:
|
||||||
continue
|
continue
|
||||||
else:
|
else:
|
||||||
|
@ -981,7 +1008,13 @@ class P4Submit(Command, P4UserMap):
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
def prepareSubmitTemplate(self):
|
def prepareSubmitTemplate(self):
|
||||||
# remove lines in the Files section that show changes to files outside the depot path we're committing into
|
"""Run "p4 change -o" to grab a change specification template.
|
||||||
|
This does not use "p4 -G", as it is nice to keep the submission
|
||||||
|
template in original order, since a human might edit it.
|
||||||
|
|
||||||
|
Remove lines in the Files section that show changes to files
|
||||||
|
outside the depot path we're committing into."""
|
||||||
|
|
||||||
template = ""
|
template = ""
|
||||||
inFilesSection = False
|
inFilesSection = False
|
||||||
for line in p4_read_pipe_lines(['change', '-o']):
|
for line in p4_read_pipe_lines(['change', '-o']):
|
||||||
|
@ -1206,11 +1239,10 @@ class P4Submit(Command, P4UserMap):
|
||||||
|
|
||||||
logMessage = extractLogMessageFromGitCommit(id)
|
logMessage = extractLogMessageFromGitCommit(id)
|
||||||
logMessage = logMessage.strip()
|
logMessage = logMessage.strip()
|
||||||
|
(logMessage, jobs) = self.separate_jobs_from_description(logMessage)
|
||||||
|
|
||||||
template = self.prepareSubmitTemplate()
|
template = self.prepareSubmitTemplate()
|
||||||
|
submitTemplate = self.prepareLogMessage(template, logMessage, jobs)
|
||||||
if self.interactive:
|
|
||||||
submitTemplate = self.prepareLogMessage(template, logMessage)
|
|
||||||
|
|
||||||
if self.preserveUser:
|
if self.preserveUser:
|
||||||
submitTemplate = submitTemplate + ("\n######## Actual user %s, modified after commit\n" % p4User)
|
submitTemplate = submitTemplate + ("\n######## Actual user %s, modified after commit\n" % p4User)
|
||||||
|
@ -1281,14 +1313,6 @@ class P4Submit(Command, P4UserMap):
|
||||||
os.remove(f)
|
os.remove(f)
|
||||||
|
|
||||||
os.remove(fileName)
|
os.remove(fileName)
|
||||||
else:
|
|
||||||
fileName = "submit.txt"
|
|
||||||
file = open(fileName, "w+")
|
|
||||||
file.write(self.prepareLogMessage(template, logMessage))
|
|
||||||
file.close()
|
|
||||||
print ("Perforce submit template written as %s. "
|
|
||||||
+ "Please review/edit and then use p4 submit -i < %s to submit directly!"
|
|
||||||
% (fileName, fileName))
|
|
||||||
|
|
||||||
# Export git tags as p4 labels. Create a p4 label and then tag
|
# Export git tags as p4 labels. Create a p4 label and then tag
|
||||||
# with that.
|
# with that.
|
||||||
|
@ -1437,8 +1461,6 @@ class P4Submit(Command, P4UserMap):
|
||||||
commit = commits[0]
|
commit = commits[0]
|
||||||
commits = commits[1:]
|
commits = commits[1:]
|
||||||
self.applyCommit(commit)
|
self.applyCommit(commit)
|
||||||
if not self.interactive:
|
|
||||||
break
|
|
||||||
|
|
||||||
if len(commits) == 0:
|
if len(commits) == 0:
|
||||||
print "All changes applied!"
|
print "All changes applied!"
|
||||||
|
|
|
@ -102,3 +102,16 @@ cleanup_git() {
|
||||||
rm -rf "$git" &&
|
rm -rf "$git" &&
|
||||||
mkdir "$git"
|
mkdir "$git"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
marshal_dump() {
|
||||||
|
what=$1 &&
|
||||||
|
line=${2:-1} &&
|
||||||
|
cat >"$TRASH_DIRECTORY/marshal-dump.py" <<-EOF &&
|
||||||
|
import marshal
|
||||||
|
import sys
|
||||||
|
for i in range($line):
|
||||||
|
d = marshal.load(sys.stdin)
|
||||||
|
print d['$what']
|
||||||
|
EOF
|
||||||
|
"$PYTHON_PATH" "$TRASH_DIRECTORY/marshal-dump.py"
|
||||||
|
}
|
||||||
|
|
|
@ -155,11 +155,6 @@ test_expect_success 'clone bare' '
|
||||||
)
|
)
|
||||||
'
|
'
|
||||||
|
|
||||||
marshal_dump() {
|
|
||||||
what=$1
|
|
||||||
"$PYTHON_PATH" -c 'import marshal, sys; d = marshal.load(sys.stdin); print d["'$what'"]'
|
|
||||||
}
|
|
||||||
|
|
||||||
# Sleep a bit so that the top-most p4 change did not happen "now". Then
|
# Sleep a bit so that the top-most p4 change did not happen "now". Then
|
||||||
# import the repo and make sure that the initial import has the same time
|
# import the repo and make sure that the initial import has the same time
|
||||||
# as the top-most change.
|
# as the top-most change.
|
||||||
|
|
|
@ -182,6 +182,161 @@ test_expect_success 'submit rename' '
|
||||||
)
|
)
|
||||||
'
|
'
|
||||||
|
|
||||||
|
#
|
||||||
|
# Converting git commit message to p4 change description, including
|
||||||
|
# parsing out the optional Jobs: line.
|
||||||
|
#
|
||||||
|
test_expect_success 'simple one-line description' '
|
||||||
|
test_when_finished cleanup_git &&
|
||||||
|
git p4 clone --dest="$git" //depot &&
|
||||||
|
(
|
||||||
|
cd "$git" &&
|
||||||
|
echo desc2 >desc2 &&
|
||||||
|
git add desc2 &&
|
||||||
|
cat >msg <<-EOF &&
|
||||||
|
One-line description line for desc2.
|
||||||
|
EOF
|
||||||
|
git commit -F - <msg &&
|
||||||
|
git config git-p4.skipSubmitEdit true &&
|
||||||
|
git p4 submit &&
|
||||||
|
change=$(p4 -G changes -m 1 //depot/... | \
|
||||||
|
marshal_dump change) &&
|
||||||
|
# marshal_dump always adds a newline
|
||||||
|
p4 -G describe $change | marshal_dump desc | sed \$d >pmsg &&
|
||||||
|
test_cmp msg pmsg
|
||||||
|
)
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'description with odd formatting' '
|
||||||
|
test_when_finished cleanup_git &&
|
||||||
|
git p4 clone --dest="$git" //depot &&
|
||||||
|
(
|
||||||
|
cd "$git" &&
|
||||||
|
echo desc3 >desc3 &&
|
||||||
|
git add desc3 &&
|
||||||
|
(
|
||||||
|
printf "subject line\n\n\tExtra tab\nline.\n\n" &&
|
||||||
|
printf "Description:\n\tBogus description marker\n\n" &&
|
||||||
|
# git commit eats trailing newlines; only use one
|
||||||
|
printf "Files:\n\tBogus descs marker\n"
|
||||||
|
) >msg &&
|
||||||
|
git commit -F - <msg &&
|
||||||
|
git config git-p4.skipSubmitEdit true &&
|
||||||
|
git p4 submit &&
|
||||||
|
change=$(p4 -G changes -m 1 //depot/... | \
|
||||||
|
marshal_dump change) &&
|
||||||
|
# marshal_dump always adds a newline
|
||||||
|
p4 -G describe $change | marshal_dump desc | sed \$d >pmsg &&
|
||||||
|
test_cmp msg pmsg
|
||||||
|
)
|
||||||
|
'
|
||||||
|
|
||||||
|
make_job() {
|
||||||
|
name="$1" &&
|
||||||
|
tab="$(printf \\t)" &&
|
||||||
|
p4 job -o | \
|
||||||
|
sed -e "/^Job:/s/.*/Job: $name/" \
|
||||||
|
-e "/^Description/{ n; s/.*/$tab job text/; }" | \
|
||||||
|
p4 job -i
|
||||||
|
}
|
||||||
|
|
||||||
|
test_expect_success 'description with Jobs section at end' '
|
||||||
|
test_when_finished cleanup_git &&
|
||||||
|
git p4 clone --dest="$git" //depot &&
|
||||||
|
(
|
||||||
|
cd "$git" &&
|
||||||
|
echo desc4 >desc4 &&
|
||||||
|
git add desc4 &&
|
||||||
|
echo 6060842 >jobname &&
|
||||||
|
(
|
||||||
|
printf "subject line\n\n\tExtra tab\nline.\n\n" &&
|
||||||
|
printf "Files:\n\tBogus files marker\n" &&
|
||||||
|
printf "Junk: 3164175\n" &&
|
||||||
|
printf "Jobs: $(cat jobname)\n"
|
||||||
|
) >msg &&
|
||||||
|
git commit -F - <msg &&
|
||||||
|
git config git-p4.skipSubmitEdit true &&
|
||||||
|
# build a job
|
||||||
|
make_job $(cat jobname) &&
|
||||||
|
git p4 submit &&
|
||||||
|
change=$(p4 -G changes -m 1 //depot/... | \
|
||||||
|
marshal_dump change) &&
|
||||||
|
# marshal_dump always adds a newline
|
||||||
|
p4 -G describe $change | marshal_dump desc | sed \$d >pmsg &&
|
||||||
|
# make sure Jobs line and all following is gone
|
||||||
|
sed "/^Jobs:/,\$d" msg >jmsg &&
|
||||||
|
test_cmp jmsg pmsg &&
|
||||||
|
# make sure p4 knows about job
|
||||||
|
p4 -G describe $change | marshal_dump job0 >job0 &&
|
||||||
|
test_cmp jobname job0
|
||||||
|
)
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'description with Jobs and values on separate lines' '
|
||||||
|
test_when_finished cleanup_git &&
|
||||||
|
git p4 clone --dest="$git" //depot &&
|
||||||
|
(
|
||||||
|
cd "$git" &&
|
||||||
|
echo desc5 >desc5 &&
|
||||||
|
git add desc5 &&
|
||||||
|
echo PROJ-6060842 >jobname1 &&
|
||||||
|
echo PROJ-6060847 >jobname2 &&
|
||||||
|
(
|
||||||
|
printf "subject line\n\n\tExtra tab\nline.\n\n" &&
|
||||||
|
printf "Files:\n\tBogus files marker\n" &&
|
||||||
|
printf "Junk: 3164175\n" &&
|
||||||
|
printf "Jobs:\n" &&
|
||||||
|
printf "\t$(cat jobname1)\n" &&
|
||||||
|
printf "\t$(cat jobname2)\n"
|
||||||
|
) >msg &&
|
||||||
|
git commit -F - <msg &&
|
||||||
|
git config git-p4.skipSubmitEdit true &&
|
||||||
|
# build two jobs
|
||||||
|
make_job $(cat jobname1) &&
|
||||||
|
make_job $(cat jobname2) &&
|
||||||
|
git p4 submit &&
|
||||||
|
change=$(p4 -G changes -m 1 //depot/... | \
|
||||||
|
marshal_dump change) &&
|
||||||
|
# marshal_dump always adds a newline
|
||||||
|
p4 -G describe $change | marshal_dump desc | sed \$d >pmsg &&
|
||||||
|
# make sure Jobs line and all following is gone
|
||||||
|
sed "/^Jobs:/,\$d" msg >jmsg &&
|
||||||
|
test_cmp jmsg pmsg &&
|
||||||
|
# make sure p4 knows about the two jobs
|
||||||
|
p4 -G describe $change >change &&
|
||||||
|
(
|
||||||
|
marshal_dump job0 <change &&
|
||||||
|
marshal_dump job1 <change
|
||||||
|
) | sort >jobs &&
|
||||||
|
cat jobname1 jobname2 | sort >expected &&
|
||||||
|
test_cmp expected jobs
|
||||||
|
)
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'description with Jobs section and bogus following text' '
|
||||||
|
test_when_finished cleanup_git &&
|
||||||
|
git p4 clone --dest="$git" //depot &&
|
||||||
|
(
|
||||||
|
cd "$git" &&
|
||||||
|
echo desc6 >desc6 &&
|
||||||
|
git add desc6 &&
|
||||||
|
echo 6060843 >jobname &&
|
||||||
|
(
|
||||||
|
printf "subject line\n\n\tExtra tab\nline.\n\n" &&
|
||||||
|
printf "Files:\n\tBogus files marker\n" &&
|
||||||
|
printf "Junk: 3164175\n" &&
|
||||||
|
printf "Jobs: $(cat jobname)\n" &&
|
||||||
|
printf "MoreJunk: 3711\n"
|
||||||
|
) >msg &&
|
||||||
|
git commit -F - <msg &&
|
||||||
|
git config git-p4.skipSubmitEdit true &&
|
||||||
|
# build a job
|
||||||
|
make_job $(cat jobname) &&
|
||||||
|
test_must_fail git p4 submit 2>err &&
|
||||||
|
test_i18ngrep "Unknown field name" err
|
||||||
|
)
|
||||||
|
'
|
||||||
|
|
||||||
test_expect_success 'kill p4d' '
|
test_expect_success 'kill p4d' '
|
||||||
kill_p4d
|
kill_p4d
|
||||||
'
|
'
|
||||||
|
|
Загрузка…
Ссылка в новой задаче