Created
September 9, 2012 14:30
-
-
Save scunz/3684702 to your computer and use it in GitHub Desktop.
Prove that git_mergebase + 2x git_revwalk can _not_ be used to find the "is 5 ahead 3 behind foo"
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
#include <assert.h> | |
#include <stdio.h> | |
#include <memory.h> | |
#include "git2.h" | |
char* gerr = 0; | |
int find_divergence_single( | |
git_repository* repo, | |
const git_oid* base, | |
const git_oid* dest, | |
int* steps ) | |
{ | |
int rc; | |
git_revwalk* walk = NULL; | |
git_oid current; | |
assert( base && repo && dest && steps ); | |
if( git_oid_cmp( base, dest ) == 0 ) | |
{ | |
*steps = 0; | |
return 0; | |
} | |
if( git_revwalk_new( &walk, repo ) < 0 ) | |
{ | |
gerr = "Cannot create a walk"; | |
return -1; | |
} | |
if( !git_revwalk_push( walk, dest ) < 0 ) | |
{ | |
gerr = "Cannot push base"; | |
return -1; | |
} | |
git_revwalk_sorting( walk, GIT_SORT_TOPOLOGICAL ); | |
while( ( rc = git_revwalk_next( ¤t, walk ) ) >= 0 ) | |
{ | |
if( rc == GIT_ITEROVER ) | |
{ | |
gerr = "dest does not follow to base"; | |
return -1; | |
} | |
else if( rc < 0 ) | |
{ | |
gerr = "Cannot walk"; | |
return -1; | |
} | |
if( git_oid_cmp( ¤t, base ) == 0 ) | |
{ | |
break; | |
} | |
++(*steps); | |
} | |
git_revwalk_free( walk ); | |
return 0; | |
} | |
int find_divergence( | |
git_repository* repo, | |
const git_oid* me, | |
const git_oid* they, | |
int* ahead, | |
int* behind ) | |
{ | |
char oid_a[41], oid_b[41], oid_c[41]; | |
assert( repo && me && they && ahead && behind ); | |
*ahead = *behind = 0; | |
git_oid merge_base; | |
if( git_merge_base( &merge_base, repo, (git_oid*)me, (git_oid*)they ) < 0 ) | |
{ | |
const git_error* e = giterr_last(); | |
printf( "ERR: %s\n", e ? e->message : "???" ); | |
gerr = "Cannot find merge base"; | |
return -2; | |
} | |
git_oid_fmt( oid_a, me ); oid_a[ 40 ] = 0; | |
git_oid_fmt( oid_b, they ); oid_b[ 40 ] = 0; | |
git_oid_fmt( oid_c, &merge_base ); oid_c[ 40 ] = 0; | |
// printf( "Base of '%s' and '%s' is '%s'\n", &oid_a[0], &oid_b[0], &oid_c[0] ); | |
if( find_divergence_single( repo, &merge_base, me, ahead ) < 0 ) | |
{ | |
return -1; | |
} | |
if( find_divergence_single( repo, &merge_base, they, behind ) < 0 ) | |
{ | |
return -1; | |
} | |
return 0; | |
} | |
git_oid tags[5]; | |
int read_tags( git_repository* repo ) | |
{ | |
int i; | |
char oidstr[41]; | |
char tagname[] = "refs/tags/t0"; | |
for( i = 0; i < 5; i++ ) | |
{ | |
tagname[ 11 ] = '1' + i; | |
if( git_reference_name_to_oid( &tags[ i ], repo, tagname ) < 0 ) | |
{ | |
return -1; | |
} | |
git_oid_fmt( oidstr, &tags[ i ] ); | |
printf( "Tag '%s' is at %s\n", &tagname[0], oidstr ); | |
} | |
return 0; | |
} | |
int main(void) | |
{ | |
int a, b, i, j, rc; | |
git_repository* repo = NULL; | |
git_threads_init(); | |
if( git_repository_open( &repo, "../merge_base_test" ) < 0 ) | |
{ | |
puts( "Cannot find repo" ); | |
return -1; | |
} | |
read_tags( repo ); | |
for( i = 0; i < 5; i++ ) | |
{ | |
for( j = 0; j < 5; j++ ) | |
{ | |
if( ( rc = find_divergence( repo, &tags[ i ], &tags[ j ], &a, &b ) ) < 0 ) | |
{ | |
printf( "Error: %s\n", gerr ); | |
if( rc != -2 ) | |
{ | |
return -1; | |
} | |
} | |
if( rc == -2 ) | |
{ | |
printf( "t%i is not related to t%i\n", | |
i+1, j+1 ); | |
} | |
else | |
{ | |
printf( "t%i is %i ahead and %i behind of t%i\n", | |
i+1, a, b, j+1 ); | |
} | |
fflush(stdout); | |
} | |
} | |
git_repository_free( repo ); | |
git_threads_shutdown(); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment