-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
approximate-picks: new API to see if commits are cherry-picks/reverts
We want some functions to check if commits are cherry-picks or reverts, based on information recorded in the commit message. Namely, substrings of the form This reverts commit ... [reversing\nchanges made to ...] cherry picked from commit ... When these strings are found, get_message_pick() can return that the specified commit is a cherry-pick or revert and what other commit the specified commit is a cherry-pick or revert of. We will use this later to implement --remerge-diff-only, where normal non-merge commits that are not cherry-picks or reverts are omitted from log/show output, and cherry-picks or reverts are shown as a diff against an automatic re-pick/re-revert. Thus, the new flag will be a way to see what changes the creator of the commit made in order to complete the cherry-pick or revert, such as removing conflict markers. Signed-off-by: Elijah Newren <[email protected]>
- Loading branch information
Showing
3 changed files
with
105 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
#include "git-compat-util.h" | ||
#include "approximate-picks.h" | ||
#include "commit.h" | ||
#include "environment.h" | ||
#include "hex.h" | ||
#include "repository.h" | ||
|
||
void get_message_pick(struct commit *commit, int *is_revert, | ||
struct commit **pick_of, struct commit **base) | ||
{ | ||
const char *message; | ||
const char *revert_msg = "This reverts commit "; | ||
const char *cherry_msg = "cherry picked from commit "; | ||
const char *revert_msg_base = "reversing\nchanges made to "; | ||
char *loc = NULL; | ||
struct object_id picked_oid; | ||
int find_base = 1; | ||
|
||
message = repo_logmsg_reencode(the_repository, commit, NULL, | ||
get_log_output_encoding()); | ||
if ((loc = strstr(message, cherry_msg))) { | ||
/* cherry-pick */ | ||
*is_revert = 0; | ||
if (get_oid_hex(loc + strlen(cherry_msg), &picked_oid)) | ||
/* Couldn't parse next text as object id */ | ||
goto not_a_pick; | ||
} else if ((loc = strstr(message, revert_msg))) { | ||
/* revert */ | ||
*is_revert = 1; | ||
if (get_oid_hex(loc + strlen(revert_msg), &picked_oid)) | ||
/* Couldn't parse next text as object id */ | ||
goto not_a_pick; | ||
if ((loc = strstr(message, revert_msg_base))) { | ||
/* revert relative to specified base */ | ||
struct object_id tmpid; | ||
if (get_oid_hex(loc + strlen(revert_msg_base), &tmpid)) | ||
/* Couldn't parse next text as object id */ | ||
goto not_a_pick; | ||
*base = lookup_commit(the_repository, &tmpid); | ||
find_base = 0; | ||
} | ||
} else | ||
/* neither */ | ||
goto not_a_pick; | ||
|
||
*pick_of = lookup_commit(the_repository, &picked_oid); | ||
if (repo_parse_commit_gently(the_repository, *pick_of, 1)) | ||
/* | ||
* Getting here means commit referenced a nonexistent commit | ||
* for what it is a cherry-pick or revert of. We treat this | ||
* as not a cherry-pick or revert. | ||
*/ | ||
goto not_a_pick; | ||
if (find_base) { | ||
struct commit_list *parents = (*pick_of)->parents; | ||
if (!parents) { | ||
*base = NULL; | ||
return; | ||
} | ||
if (parents->next != NULL) | ||
/* | ||
* Getting here means that either a commit said it was | ||
* a revert of a merge without telling us which parent, | ||
* or it claimed it was a cherry-pick of a merge which | ||
* makes no sense. | ||
*/ | ||
goto not_a_pick; | ||
*base = parents->item; | ||
} | ||
parse_commit_or_die(*base); | ||
return; | ||
|
||
not_a_pick: | ||
*is_revert = -1; | ||
*pick_of = NULL; | ||
*base = NULL; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
#ifndef APPROXIMATE_PICKS_H | ||
#define APPROXIMATE_PICKS_H | ||
|
||
struct commit; | ||
|
||
/* | ||
* Determine if the commit message for commit claims this is a cherry-pick or | ||
* revert of another commit, which exists in this repo. Possible return | ||
* values: | ||
* | ||
* If commit message claims it is a cherry-pick: | ||
* *is_revert: 0 | ||
* *pick_of: points to what commit is a cherry-pick of | ||
* *base: points to parent of *pick_of (possibly NULL) | ||
* If commit message claims it is a revert: | ||
* *is_revert: 1 | ||
* *pick_of: points to what commit is a revert of | ||
* *base: points to appropriate parent of *pick_of (possibly NULL) | ||
* Otherwise: | ||
* *is_revert: -1 | ||
* *pick_of: NULL | ||
* *base: NULL | ||
*/ | ||
void get_message_pick(struct commit *commit, int *is_revert, | ||
struct commit **pick_of, struct commit **base); | ||
|
||
#endif /* APPROXIMATE_PICKS_H */ |