What follows is three example commits. In all cases 'git show' explains correctly, yet for merge commits the two API's give inconsistent results.
Consider this merge commit #1, 'git show' *correctly shows the changes to the files* (file A was developer resolved, file B was auto-merged, file C was included w/out file-level merge changes (no new revision)):
$ git show c47af8deac6b87a
commit c47af8deac6b87a35c54f750166a13089c35b770 (HEAD -> master, origin/PR2, PR2)
Merge: 4a7b7ed 705cb5f
Author: Joe
Date: Fri Mar 18 14:27:03 2022 -0400
Merge branch 'master' into PR2
diff --cc A
index bb62e45,c875e2d..695279f
--- a/A
+++ b/A
@@@ -1,3 -1,7 +1,8 @@@
adios
more stuff
+take that!
+ hello
+ what are we doing
+ this is it
+ more of the same
+ gimme a break
diff --cc B
index fecdf68,864a49b..aa01e7f
--- a/B
+++ b/B
@@@ -1,6 -1,5 +1,4 @@@
-guten tag
this is getting ridiculous
- what now?
- ho hum
goodbye
more changes
uh-oh
However the Java API shows three changes (when iterating through the changesets for that commit):
2022-03-18 19:46:16,817 WARN [c.o.s.r.ScriptBindingsManager]: Type: MODIFY
2022-03-18 19:46:16,817 WARN [c.o.s.r.ScriptBindingsManager]: Path: A
2022-03-18 19:46:16,817 WARN [c.o.s.r.ScriptBindingsManager]: Type: MODIFY
2022-03-18 19:46:16,818 WARN [c.o.s.r.ScriptBindingsManager]: Path: B
2022-03-18 19:46:16,818 WARN [c.o.s.r.ScriptBindingsManager]: Type: MODIFY
2022-03-18 19:46:16,818 WARN [c.o.s.r.ScriptBindingsManager]: Path: C
While the REST API shows no changes (.../commits/c47af8d/changes):
{"fromHash":null,"toHash":"c47af8d","properties":{},"values":[],"size":0,"isLastPage":true,"start":0,"limit":25,"nextPageStart":null}
Consider this merge commit #2, 'git show' *correctly shows that there are no changes to any files* (files A and C were included, but no new file revisions via file-level merge):
$ git show 8907e98fb71ffca612
commit 8907e98fb71ffca6120f703d0e43be4787dd173e
Merge: edb85da 2d76267
Author: Joe
Date: Thu Mar 17 12:57:40 2022 -0400
Merge branch 'master' into PR2
However the Java API shows two changes:
2022-03-18 19:53:38,354 WARN [c.o.s.r.ScriptBindingsManager]: Type: MODIFY
2022-03-18 19:53:38,373 WARN [c.o.s.r.ScriptBindingsManager]: Path: A
2022-03-18 19:53:38,374 WARN [c.o.s.r.ScriptBindingsManager]: Type: MODIFY
2022-03-18 19:53:38,374 WARN [c.o.s.r.ScriptBindingsManager]: Path: C
While the REST API shows no changes (.../commits/8907e98/changes):
{"fromHash":null,"toHash":"8907e98","properties":{},"values":[],"size":0,"isLastPage":true,"start":0,"limit":25,"nextPageStart":null}
For a simple (non-merge) commit, results are as expected (file A is modified):
$ git show 4a7b7ed55
commit 4a7b7ed55512a5814292ba6b1689a781c4dc225b
Author: Joe
Date: Fri Mar 18 14:24:44 2022 -0400
PR2
diff --git a/A b/A
index 76b9b5a..bb62e45 100644
--- a/A
+++ b/A
@@ -1,2 +1,3 @@
adios
more stuff
+take that!
2022-03-18 20:11:46,977 WARN [c.o.s.r.ScriptBindingsManager]: Type: MODIFY
2022-03-18 20:11:47,012 WARN [c.o.s.r.ScriptBindingsManager]: Path: A
{"fromHash":null,"toHash":"4a7b7ed55","properties":{},"values":[{"contentId":"bb62e451e87164abcba481ef8f73d719230e0b62","fromContentId":"76b9b5ab7d2242c33ab6ee0d9ede24233add0b66","path":{"components":["A"],"parent":"","name":"A","toString":"A"},"executable":false,"percentUnchanged":-1,"type":"MODIFY","nodeType":"FILE","srcExecutable":false,"links":{...},"properties":{"gitChangeType":"MODIFY"}}],"size":1,"isLastPage":true,"start":0,"limit":25,"nextPageStart":null}
Can execute the 'git show' command from bitbucket...
// check if the commit has new file revisions
// use 'git show' and count the number of new file revisionsdef outputHandler = new SingleLineOutputHandler()
gitCommandBuilderFactory.builder(commit.repository)
.command("show")
.argument("--oneline")
.argument("--name-status")
.argument(commit.id)
.build(outputHandler)
.call()
def new_file_revisions = (outputHandler.getOutput().split("\t").size()-1)
From a top-level perspective, we've implemented a pre-receive hook to prevent pushes to master if all the files don't have review credit in Crucible...
...
def REVIEWS_PATH = 'rest-service-fe/search-v1/queryAsRows/'
commitCallback =
new PreRepositoryHookCommitCallback() {
@Override boolean onCommitAdded(@Nonnull CommitAddedDetails commitDetails) {
def commit = commitDetails.commit
// for commits on master, check to see if the commit includes file revisions
// that are part of a CLOSED review
if (commitDetails.ref.id.startsWith("refs/heads/master")) {
// check if the commit has new file revisions
// use 'git show' and count the number of occurrences of diff output
def outputHandler = new SingleLineOutputHandler()
gitCommandBuilderFactory.builder(commit.repository)
.command("show")
.argument("--oneline")
.argument("--name-status")
.argument(commit.id)
.build(outputHandler)
.call()
def int new_file_revisions = (outputHandler.getOutput().split("\t").size()-1)
if (new_file_revisions > 0) {
// check Crucible
def REVIEWS_QUERY = URLEncoder.encode("select revisions where csid = ${commit.id} and reviewed return count(revisions)", "UTF-8")
def getReviews = authenticatedRequestFactory
.createRequest(GET, "${FISHEYE_URL}${REVIEWS_PATH}${commit.repository.name}?query=${REVIEWS_QUERY}")
.addHeader("Accept", "application/json")
.addHeader("Content-Type", "application/json")
// {headings=[countReviews], row=[{item=[0]}]}
def result = getReviews.execute(handler)["row"]["item"][0] as ArrayList
def reviewedRevisions = result[0] as int
if (new_file_revisions == reviewedRevisions) {
// allow commits w/ reviewed revisions
return true
} else {
// the number or reviewed revisions does not match the number of new file revisions
resultBuilder.veto("*** Unreviewed commit to master!!! ***",
"*** Commit ID: " + commit.id +
" *** New file revisions: " + new_file_revisions +
" *** Reviewed revisions: " + reviewedRevisions + " ***") return false
}
} else {
// allow commit w/ no new file revisions (likely a clean merge-commit)
return true
}
} else {
// allow non-master commits
return true
}
}
@Override RepositoryHookResult getResult() {
resultBuilder.build()
}
}
commitFilters << RepositoryHookCommitFilter.ADDED_TO_ANY_REF
return RepositoryHookResult.accepted()
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Online forums and learning are now in one easy-to-use experience.
By continuing, you accept the updated Community Terms of Use and acknowledge the Privacy Policy. Your public name, photo, and achievements may be publicly visible and available in search engines.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.