commit - 497a59156be73918988396d3f7378fb8c7b6da8d
commit + db0dfdd7e5c2c5a38ed7c3291a0615132bcb5945
blob - 9c2a6eea387f21e2d874e520ee11a682facc654b
blob + 1bc4c535c2483d8ebfffd91a5553da6d6da60ce8
--- lib/patch.c
+++ lib/patch.c
{
const struct got_error *err = NULL;
struct got_blob_object *blob = NULL;
- struct got_object_id id;
+ struct got_object_id id, *idptr, *matched_id = NULL;
*fp = NULL;
*path = NULL;
- if (!got_parse_sha1_digest(id.sha1, blobid))
- return got_error(GOT_ERR_BAD_OBJ_ID_STR);
+ if (strlen(blobid) != SHA1_DIGEST_STRING_LENGTH - 1) {
+ err = got_repo_match_object_id(&matched_id, NULL, blobid,
+ GOT_OBJ_TYPE_BLOB, NULL /* do not resolve tags */,
+ repo);
+ if (err)
+ return err;
+ idptr = matched_id;
+ } else {
+ if (!got_parse_sha1_digest(id.sha1, blobid))
+ return got_error(GOT_ERR_BAD_OBJ_ID_STR);
+ idptr = &id;
+ }
- err = got_object_open_as_blob(&blob, repo, &id, 8192);
+ err = got_object_open_as_blob(&blob, repo, idptr, 8192);
if (err)
goto done;
done:
if (blob)
got_object_blob_close(blob);
+ if (matched_id != NULL)
+ free(matched_id);
if (err) {
if (*fp != NULL)
fclose(*fp);
* ignore failures to open this blob, we might have
* parsed gibberish.
*/
- if (err && !(err->code == GOT_ERR_ERRNO && errno == ENOENT))
+ if (err && !(err->code == GOT_ERR_ERRNO && errno == ENOENT) &&
+ err->code != GOT_ERR_NO_OBJ)
return err;
else if (err == NULL)
do_merge = 1;
blob - 14191697a10b4dbbc2cd5609d898d7830564529a
blob + d6eea51f8d3203ae05b110adaac04ee330bd4d28
--- libexec/got-read-patch/got-read-patch.c
+++ libexec/got-read-patch/got-read-patch.c
}
static const struct got_error *
-blobid(const char *line, char **blob)
+blobid(const char *line, char **blob, int git)
{
uint8_t digest[SHA1_DIGEST_LENGTH];
size_t len;
if ((*blob = strndup(line, len)) == NULL)
return got_error_from_errno("strndup");
- if (!got_parse_sha1_digest(digest, *blob)) {
+ if (!git && !got_parse_sha1_digest(digest, *blob)) {
/* silently ignore invalid blob ids */
free(*blob);
*blob = NULL;
err = filename(line+4, &new);
} else if (!git && !strncmp(line, "blob - ", 7)) {
free(blob);
- err = blobid(line + 7, &blob);
+ err = blobid(line + 7, &blob, git);
} else if (rename && !strncmp(line, "rename to ", 10)) {
free(new);
err = filename(line + 10, &new);
} else if (git && !strncmp(line, "similarity index 100%", 21))
rename = 1;
- else if (!strncmp(line, "diff --git a/", 13)) {
+ else if (git && !strncmp(line, "index ", 6)) {
+ free(blob);
+ err = blobid(line + 6, &blob, git);
+ } else if (!strncmp(line, "diff --git a/", 13)) {
git = 1;
free(commitid);
commitid = NULL;
blob = NULL;
} else if (!git && !strncmp(line, "diff ", 5)) {
free(commitid);
- err = blobid(line + 5, &commitid);
+ err = blobid(line + 5, &commitid, git);
} else if (!git && !strncmp(line, "commit - ", 9)) {
free(commitid);
- err = blobid(line + 9, &commitid);
+ err = blobid(line + 9, &commitid, git);
}
if (err)
blob - 9fb1dd39304f1cd716283dd5684a1162ee8f745c
blob + 51903218ccbe2f14d00ba02be9bbc8ead7c2f1e4
--- regress/cmdline/patch.sh
+++ regress/cmdline/patch.sh
ret=$?
if [ $ret -ne 0 ]; then
diff -u $testroot/wt/numbers $testroot/wt/numbers.expected
+ fi
+ test_done $testroot $ret
+}
+
+test_patch_merge_gitdiff() {
+ local testroot=`test_init patch_merge_gitdiff`
+
+ jot 10 > $testroot/repo/numbers
+ (cd $testroot/repo && git add numbers && \
+ git_commit $testroot/repo -m "nums")
+ ret=$?
+ if [ $ret -ne 0 ]; then
+ test_done $testroot $ret
+ return 1
+ fi
+
+ jot 10 | sed 's/4/four/g' > $testroot/repo/numbers
+ (cd $testroot/repo && git diff > $testroot/old.diff)
+ ret=$?
+ if [ $ret -ne 0 ]; then
+ test_done $testroot $ret
+ return 1
+ fi
+
+ # restore numbers
+ jot 10 > $testroot/repo/numbers
+
+ jot 10 | sed 's/6/six/g' > $testroot/repo/numbers
+ (cd $testroot/repo && git add numbers && \
+ git_commit $testroot/repo -m "edit")
+ ret=$?
+ if [ $ret -ne 0 ]; then
+ test_done $testroot $ret
+ return 1
+ fi
+
+ # now work with got:
+ got checkout $testroot/repo $testroot/wt > /dev/null
+ ret=$?
+ if [ $ret -ne 0 ]; then
+ test_done $testroot $ret
+ return 1
+ fi
+
+ (cd $testroot/wt && got patch $testroot/old.diff) > $testroot/stdout
+ ret=$?
+ if [ $ret -ne 0 ]; then
+ test_done $testroot $ret
+ return 1
fi
+
+ echo 'G numbers' > $testroot/stdout.expected
+ cmp -s $testroot/stdout $testroot/stdout.expected
+ ret=$?
+ if [ $ret -ne 0 ]; then
+ diff -u $testroot/stdout $testroot/stdout.expected
+ fi
test_done $testroot $ret
}
ret=$?
if [ $ret -ne 0 ]; then
diff -u $testroot/stdout.expected $testroot/stdout
+ test_done $testroot $ret
+ return 1
fi
+
+ # try again with a git-style diff
+
+ cat <<EOF > $testroot/wt/patch
+diff --git a/alpha b/alpha
+index 0123456789ab..abcdef012345 100644
+--- a/alpha
++++ b/alpha
+@@ -1 +1 @@
+-alpha
++ALPHA
+EOF
+
+ (cd $testroot/wt && got revert alpha > /dev/null && got patch patch) \
+ > $testroot/stdout
+ ret=$?
+ if [ $ret -ne 0 ]; then
+ test_done $testroot $ret
+ return 1
+ fi
+
+ echo 'M alpha' > $testroot/stdout.expected
+ cmp -s $testroot/stdout.expected $testroot/stdout
+ ret=$?
+ if [ $ret -ne 0 ]; then
+ diff -u $testroot/stdout.expected $testroot/stdout
+ fi
test_done $testroot $ret
}
run_test test_patch_relpath_with_path_prefix
run_test test_patch_reverse
run_test test_patch_merge_simple
+run_test test_patch_merge_gitdiff
run_test test_patch_merge_conflict
run_test test_patch_merge_unknown_blob