Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
G
git2
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
lvzhengyang
git2
Commits
d1f33156
Commit
d1f33156
authored
Apr 13, 2012
by
Vicent Martí
Browse files
Options
Browse Files
Download
Plain Diff
Merge remote-tracking branch 'carlosmn/revwalk-merge-base' into new-error-handling
parents
fcb2164f
eb8117b8
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
431 additions
and
121 deletions
+431
-121
include/git2.h
+1
-0
include/git2/merge.h
+35
-0
include/git2/revwalk.h
+22
-0
src/revwalk.c
+318
-118
tests-clar/revwalk/basic.c
+18
-3
tests-clar/revwalk/mergebase.c
+37
-0
No files found.
include/git2.h
View file @
d1f33156
...
...
@@ -22,6 +22,7 @@
#include "git2/repository.h"
#include "git2/revwalk.h"
#include "git2/merge.h"
#include "git2/refs.h"
#include "git2/reflog.h"
...
...
include/git2/merge.h
0 → 100644
View file @
d1f33156
/*
* Copyright (C) 2009-2012 the libgit2 contributors
*
* This file is part of libgit2, distributed under the GNU GPL v2 with
* a Linking Exception. For full terms see the included COPYING file.
*/
#ifndef INCLUDE_git_merge_h__
#define INCLUDE_git_merge_h__
#include "common.h"
#include "types.h"
#include "oid.h"
/**
* @file git2/merge.h
* @brief Git merge-base routines
* @defgroup git_revwalk Git merge-base routines
* @ingroup Git
* @{
*/
GIT_BEGIN_DECL
/**
* Find a merge base between two commits
*
* @param out the OID of a merge base between 'one' and 'two'
* @param repo the repository where the commits exist
* @param one one of the commits
* @param two the other commit
*/
GIT_EXTERN
(
int
)
git_merge_base
(
git_oid
*
out
,
git_repository
*
repo
,
git_oid
*
one
,
git_oid
*
two
);
/** @} */
GIT_END_DECL
#endif
include/git2/revwalk.h
View file @
d1f33156
...
...
@@ -164,6 +164,28 @@ GIT_EXTERN(int) git_revwalk_hide_glob(git_revwalk *walk, const char *glob);
GIT_EXTERN
(
int
)
git_revwalk_hide_head
(
git_revwalk
*
walk
);
/**
* Push the OID pointed to by a reference
*
* The reference must point to a commit.
*
* @param walk the walker being used for the traversal
* @param refname the referece to push
* @return GIT_SUCCESS or an error code
*/
GIT_EXTERN
(
int
)
git_revwalk_push_ref
(
git_revwalk
*
walk
,
const
char
*
refname
);
/**
* Hide the OID pointed to by a reference
*
* The reference must point to a commit.
*
* @param walk the walker being used for the traversal
* @param refname the referece to hide
* @return GIT_SUCCESS or an error code
*/
GIT_EXTERN
(
int
)
git_revwalk_hide_ref
(
git_revwalk
*
walk
,
const
char
*
refname
);
/**
* Get the next commit from the revision walk.
*
* The initial call to this method is *not* blocking when
...
...
src/revwalk.c
View file @
d1f33156
...
...
@@ -12,16 +12,23 @@
#include "pqueue.h"
#include "git2/revwalk.h"
#include "git2/merge.h"
#include <regex.h>
#define PARENT1 (1 << 0)
#define PARENT2 (1 << 1)
#define RESULT (1 << 2)
#define STALE (1 << 3)
typedef
struct
commit_object
{
git_oid
oid
;
uint32_t
time
;
unsigned
int
seen
:
1
,
uninteresting
:
1
,
topo_delay
:
1
,
parsed
:
1
;
parsed
:
1
,
flags
:
4
;
unsigned
short
in_degree
;
unsigned
short
out_degree
;
...
...
@@ -53,17 +60,46 @@ struct git_revwalk {
unsigned
walking
:
1
;
unsigned
int
sorting
;
/* merge base calculation */
commit_object
*
one
;
git_vector
twos
;
};
static
int
commit_time_cmp
(
void
*
a
,
void
*
b
)
{
commit_object
*
commit_a
=
(
commit_object
*
)
a
;
commit_object
*
commit_b
=
(
commit_object
*
)
b
;
return
(
commit_a
->
time
<
commit_b
->
time
);
}
static
commit_list
*
commit_list_insert
(
commit_object
*
item
,
commit_list
**
list_p
)
{
commit_list
*
new_list
=
git__malloc
(
sizeof
(
commit_list
));
if
(
new_list
==
NULL
)
return
NULL
;
new_list
->
item
=
item
;
new_list
->
next
=
*
list_p
;
*
list_p
=
new_list
;
return
new_list
;
}
static
commit_list
*
commit_list_insert_by_date
(
commit_object
*
item
,
commit_list
**
list_p
)
{
commit_list
**
pp
=
list_p
;
commit_list
*
p
;
while
((
p
=
*
pp
)
!=
NULL
)
{
if
(
commit_time_cmp
(
p
->
item
,
item
)
<
0
)
break
;
pp
=
&
p
->
next
;
}
return
commit_list_insert
(
item
,
pp
);
}
static
void
commit_list_free
(
commit_list
**
list_p
)
{
commit_list
*
list
=
*
list_p
;
...
...
@@ -89,14 +125,6 @@ static commit_object *commit_list_pop(commit_list **stack)
return
item
;
}
static
int
commit_time_cmp
(
void
*
a
,
void
*
b
)
{
commit_object
*
commit_a
=
(
commit_object
*
)
a
;
commit_object
*
commit_b
=
(
commit_object
*
)
b
;
return
(
commit_a
->
time
<
commit_b
->
time
);
}
static
uint32_t
object_table_hash
(
const
void
*
key
,
int
hash_id
)
{
uint32_t
r
;
...
...
@@ -186,38 +214,43 @@ static int commit_quick_parse(git_revwalk *walk, commit_object *commit, git_rawo
}
commit
->
parents
=
alloc_parents
(
commit
,
parents
);
if
(
commit
->
parents
==
NULL
)
return
GIT_ENOMEM
;
GITERR_CHECK_ALLOC
(
commit
->
parents
);
buffer
=
parents_start
;
for
(
i
=
0
;
i
<
parents
;
++
i
)
{
git_oid
oid
;
if
(
git_oid_fromstr
(
&
oid
,
(
char
*
)
buffer
+
strlen
(
"parent "
))
<
GIT_SUCCESS
)
return
git__throw
(
GIT_EOBJCORRUPTED
,
"Failed to parse commit. Parent object is corrupted"
)
;
if
(
git_oid_fromstr
(
&
oid
,
(
char
*
)
buffer
+
strlen
(
"parent "
))
<
0
)
return
-
1
;
commit
->
parents
[
i
]
=
commit_lookup
(
walk
,
&
oid
);
if
(
commit
->
parents
[
i
]
==
NULL
)
return
GIT_ENOMEM
;
return
-
1
;
buffer
+=
parent_len
;
}
commit
->
out_degree
=
(
unsigned
short
)
parents
;
if
((
buffer
=
memchr
(
buffer
,
'\n'
,
buffer_end
-
buffer
))
==
NULL
)
return
git__throw
(
GIT_EOBJCORRUPTED
,
"Failed to parse commit. Object is corrupted"
);
if
((
buffer
=
memchr
(
buffer
,
'\n'
,
buffer_end
-
buffer
))
==
NULL
)
{
giterr_set
(
GITERR_ODB
,
"Failed to parse commit. Object is corrupted"
);
return
-
1
;
}
buffer
=
memchr
(
buffer
,
'>'
,
buffer_end
-
buffer
);
if
(
buffer
==
NULL
)
return
git__throw
(
GIT_EOBJCORRUPTED
,
"Failed to parse commit. Can't find author"
);
if
(
buffer
==
NULL
)
{
giterr_set
(
GITERR_ODB
,
"Failed to parse commit. Can't find author"
);
return
-
1
;
}
if
(
git__strtol32
(
&
commit_time
,
(
char
*
)
buffer
+
2
,
NULL
,
10
)
<
GIT_SUCCESS
)
return
git__throw
(
GIT_EOBJCORRUPTED
,
"Failed to parse commit. Can't parse commit time"
);
if
(
git__strtol32
(
&
commit_time
,
(
char
*
)
buffer
+
2
,
NULL
,
10
)
<
0
)
{
giterr_set
(
GITERR_ODB
,
"Failed to parse commit. Can't parse commit time"
);
return
-
1
;
}
commit
->
time
=
(
time_t
)
commit_time
;
commit
->
parsed
=
1
;
return
GIT_SUCCESS
;
return
0
;
}
static
int
commit_parse
(
git_revwalk
*
walk
,
commit_object
*
commit
)
...
...
@@ -226,19 +259,159 @@ static int commit_parse(git_revwalk *walk, commit_object *commit)
int
error
;
if
(
commit
->
parsed
)
return
GIT_SUCCESS
;
return
0
;
if
((
error
=
git_odb_read
(
&
obj
,
walk
->
odb
,
&
commit
->
oid
))
<
GIT_SUCCESS
)
return
git__rethrow
(
error
,
"Failed to parse commit. Can't read object"
)
;
if
((
error
=
git_odb_read
(
&
obj
,
walk
->
odb
,
&
commit
->
oid
))
<
0
)
return
-
1
;
if
(
obj
->
raw
.
type
!=
GIT_OBJ_COMMIT
)
{
git_odb_object_free
(
obj
);
return
git__throw
(
GIT_EOBJTYPE
,
"Failed to parse commit. Object is no commit object"
);
giterr_set
(
GITERR_INVALID
,
"Failed to parse commit. Object is no commit object"
);
return
-
1
;
}
error
=
commit_quick_parse
(
walk
,
commit
,
&
obj
->
raw
);
git_odb_object_free
(
obj
);
return
error
==
GIT_SUCCESS
?
GIT_SUCCESS
:
git__rethrow
(
error
,
"Failed to parse commit"
);
return
error
;
}
static
int
interesting
(
git_pqueue
*
list
)
{
unsigned
int
i
;
for
(
i
=
1
;
i
<
git_pqueue_size
(
list
);
i
++
)
{
commit_object
*
commit
=
list
->
d
[
i
];
if
((
commit
->
flags
&
STALE
)
==
0
)
return
1
;
}
return
0
;
}
static
int
merge_bases_many
(
commit_list
**
out
,
git_revwalk
*
walk
,
commit_object
*
one
,
git_vector
*
twos
)
{
int
error
;
unsigned
int
i
;
commit_object
*
two
;
commit_list
*
result
=
NULL
,
*
tmp
=
NULL
;
git_pqueue
list
;
/* if the commit is repeated, we have a our merge base already */
git_vector_foreach
(
twos
,
i
,
two
)
{
if
(
one
==
two
)
return
commit_list_insert
(
one
,
out
)
?
0
:
-
1
;
}
if
(
git_pqueue_init
(
&
list
,
twos
->
length
*
2
,
commit_time_cmp
)
<
0
)
return
-
1
;
if
(
commit_parse
(
walk
,
one
)
<
0
)
return
-
1
;
one
->
flags
|=
PARENT1
;
if
(
git_pqueue_insert
(
&
list
,
one
)
<
0
)
return
-
1
;
git_vector_foreach
(
twos
,
i
,
two
)
{
commit_parse
(
walk
,
two
);
two
->
flags
|=
PARENT2
;
if
(
git_pqueue_insert
(
&
list
,
two
)
<
0
)
return
-
1
;
}
/* as long as there are non-STALE commits */
while
(
interesting
(
&
list
))
{
commit_object
*
commit
;
int
flags
;
commit
=
git_pqueue_pop
(
&
list
);
flags
=
commit
->
flags
&
(
PARENT1
|
PARENT2
|
STALE
);
if
(
flags
==
(
PARENT1
|
PARENT2
))
{
if
(
!
(
commit
->
flags
&
RESULT
))
{
commit
->
flags
|=
RESULT
;
if
(
commit_list_insert
(
commit
,
&
result
)
==
NULL
)
return
-
1
;
}
/* we mark the parents of a merge stale */
flags
|=
STALE
;
}
for
(
i
=
0
;
i
<
commit
->
out_degree
;
i
++
)
{
commit_object
*
p
=
commit
->
parents
[
i
];
if
((
p
->
flags
&
flags
)
==
flags
)
continue
;
if
((
error
=
commit_parse
(
walk
,
p
))
<
GIT_SUCCESS
)
return
error
;
p
->
flags
|=
flags
;
if
(
git_pqueue_insert
(
&
list
,
p
)
<
0
)
return
-
1
;
}
}
git_pqueue_free
(
&
list
);
/* filter out any stale commits in the results */
tmp
=
result
;
result
=
NULL
;
while
(
tmp
)
{
struct
commit_list
*
next
=
tmp
->
next
;
if
(
!
(
tmp
->
item
->
flags
&
STALE
))
if
(
commit_list_insert_by_date
(
tmp
->
item
,
&
result
)
==
NULL
)
return
-
1
;
git__free
(
tmp
);
tmp
=
next
;
}
*
out
=
result
;
return
0
;
}
int
git_merge_base
(
git_oid
*
out
,
git_repository
*
repo
,
git_oid
*
one
,
git_oid
*
two
)
{
git_revwalk
*
walk
;
git_vector
list
;
commit_list
*
result
=
NULL
;
commit_object
*
commit
;
void
*
contents
[
1
];
if
(
git_revwalk_new
(
&
walk
,
repo
)
<
0
)
return
-
1
;
commit
=
commit_lookup
(
walk
,
two
);
if
(
commit
==
NULL
)
goto
on_error
;
/* This is just one value, so we can do it on the stack */
memset
(
&
list
,
0x0
,
sizeof
(
git_vector
));
contents
[
0
]
=
commit
;
list
.
length
=
1
;
list
.
contents
=
contents
;
commit
=
commit_lookup
(
walk
,
one
);
if
(
commit
==
NULL
)
goto
on_error
;
if
(
merge_bases_many
(
&
result
,
walk
,
commit
,
&
list
)
<
0
)
goto
on_error
;
if
(
!
result
)
{
git_revwalk_free
(
walk
);
return
GIT_ENOTFOUND
;
}
git_oid_cpy
(
out
,
&
result
->
item
->
oid
);
commit_list_free
(
&
result
);
git_revwalk_free
(
walk
);
return
0
;
on_error:
git_revwalk_free
(
walk
);
return
-
1
;
}
static
void
mark_uninteresting
(
commit_object
*
commit
)
...
...
@@ -248,6 +421,10 @@ static void mark_uninteresting(commit_object *commit)
commit
->
uninteresting
=
1
;
/* This means we've reached a merge base, so there's no need to walk any more */
if
((
commit
->
flags
&
(
RESULT
|
STALE
))
==
RESULT
)
return
;
for
(
i
=
0
;
i
<
commit
->
out_degree
;
++
i
)
if
(
!
commit
->
parents
[
i
]
->
uninteresting
)
mark_uninteresting
(
commit
->
parents
[
i
]);
...
...
@@ -255,18 +432,16 @@ static void mark_uninteresting(commit_object *commit)
static
int
process_commit
(
git_revwalk
*
walk
,
commit_object
*
commit
,
int
hide
)
{
int
error
;
if
(
hide
)
mark_uninteresting
(
commit
);
if
(
commit
->
seen
)
return
GIT_SUCCESS
;
return
0
;
commit
->
seen
=
1
;
if
(
(
error
=
commit_parse
(
walk
,
commit
))
<
GIT_SUCCESS
)
return
git__rethrow
(
error
,
"Failed to process commit"
)
;
if
(
commit_parse
(
walk
,
commit
)
<
0
)
return
-
1
;
return
walk
->
enqueue
(
walk
,
commit
);
}
...
...
@@ -274,13 +449,13 @@ static int process_commit(git_revwalk *walk, commit_object *commit, int hide)
static
int
process_commit_parents
(
git_revwalk
*
walk
,
commit_object
*
commit
)
{
unsigned
short
i
;
int
error
=
GIT_SUCCESS
;
for
(
i
=
0
;
i
<
commit
->
out_degree
&&
error
==
GIT_SUCCESS
;
++
i
)
{
error
=
process_commit
(
walk
,
commit
->
parents
[
i
],
commit
->
uninteresting
);
for
(
i
=
0
;
i
<
commit
->
out_degree
;
++
i
)
{
if
(
process_commit
(
walk
,
commit
->
parents
[
i
],
commit
->
uninteresting
)
<
0
)
return
-
1
;
}
return
error
==
GIT_SUCCESS
?
GIT_SUCCESS
:
git__rethrow
(
error
,
"Failed to process commit parents"
)
;
return
0
;
}
static
int
push_commit
(
git_revwalk
*
walk
,
const
git_oid
*
oid
,
int
uninteresting
)
...
...
@@ -289,9 +464,17 @@ static int push_commit(git_revwalk *walk, const git_oid *oid, int uninteresting)
commit
=
commit_lookup
(
walk
,
oid
);
if
(
commit
==
NULL
)
return
git__throw
(
GIT_ENOTFOUND
,
"Failed to push commit. Object not found"
)
;
return
-
1
;
return
process_commit
(
walk
,
commit
,
uninteresting
);
commit
->
uninteresting
=
uninteresting
;
if
(
walk
->
one
==
NULL
&&
!
uninteresting
)
{
walk
->
one
=
commit
;
}
else
{
if
(
git_vector_insert
(
&
walk
->
twos
,
commit
)
<
0
)
return
-
1
;
}
return
0
;
}
int
git_revwalk_push
(
git_revwalk
*
walk
,
const
git_oid
*
oid
)
...
...
@@ -307,6 +490,25 @@ int git_revwalk_hide(git_revwalk *walk, const git_oid *oid)
return
push_commit
(
walk
,
oid
,
1
);
}
static
int
push_ref
(
git_revwalk
*
walk
,
const
char
*
refname
,
int
hide
)
{
git_reference
*
ref
,
*
resolved
;
int
error
;
if
(
git_reference_lookup
(
&
ref
,
walk
->
repo
,
refname
)
<
0
)
return
-
1
;
error
=
git_reference_resolve
(
&
resolved
,
ref
);
git_reference_free
(
ref
);
if
(
error
<
0
)
return
-
1
;
error
=
push_commit
(
walk
,
git_reference_oid
(
resolved
),
hide
);
git_reference_free
(
resolved
);
return
error
;
}
struct
push_cb_data
{
git_revwalk
*
walk
;
const
char
*
glob
;
...
...
@@ -317,30 +519,16 @@ static int push_glob_cb(const char *refname, void *data_)
{
struct
push_cb_data
*
data
=
(
struct
push_cb_data
*
)
data_
;
if
(
!
git__fnmatch
(
data
->
glob
,
refname
,
0
))
{
git_reference
*
ref
,
*
resolved
;
int
error
;
error
=
git_reference_lookup
(
&
ref
,
data
->
walk
->
repo
,
refname
);
if
(
error
<
GIT_SUCCESS
)
return
error
;
error
=
git_reference_resolve
(
&
resolved
,
ref
);
git_reference_free
(
ref
);
if
(
error
<
GIT_SUCCESS
)
return
error
;
error
=
push_commit
(
data
->
walk
,
git_reference_oid
(
resolved
),
data
->
hide
);
git_reference_free
(
resolved
);
return
error
;
}
if
(
!
git__fnmatch
(
data
->
glob
,
refname
,
0
))
return
push_ref
(
data
->
walk
,
refname
,
data
->
hide
);
return
GIT_SUCCESS
;
return
0
;
}
static
int
push_glob
(
git_revwalk
*
walk
,
const
char
*
glob
,
int
hide
)
{
git_buf
buf
=
GIT_BUF_INIT
;
struct
push_cb_data
data
;
int
error
;
regex_t
preg
;
assert
(
walk
&&
glob
);
...
...
@@ -355,28 +543,32 @@ static int push_glob(git_revwalk *walk, const char *glob, int hide)
/* If no '?', '*' or '[' exist, we append '/ *' to the glob */
memset
(
&
preg
,
0x0
,
sizeof
(
regex_t
));
if
(
regcomp
(
&
preg
,
"[?*[]"
,
REG_EXTENDED
))
{
error
=
git__throw
(
GIT_EOSERR
,
"Regex failed to compile"
);
goto
cleanup
;
giterr_set
(
GITERR_OS
,
"Regex failed to compile"
);
git_buf_free
(
&
buf
);
return
-
1
;
}
if
(
regexec
(
&
preg
,
glob
,
0
,
NULL
,
0
))
git_buf_puts
(
&
buf
,
"/*"
);
if
(
git_buf_oom
(
&
buf
))
{
error
=
GIT_ENOMEM
;
goto
cleanup
;
}
if
(
git_buf_oom
(
&
buf
))
goto
on_error
;
data
.
walk
=
walk
;
data
.
glob
=
git_buf_cstr
(
&
buf
);
data
.
hide
=
hide
;
error
=
git_reference_foreach
(
walk
->
repo
,
GIT_REF_LISTALL
,
push_glob_cb
,
&
data
);
if
(
git_reference_foreach
(
walk
->
repo
,
GIT_REF_LISTALL
,
push_glob_cb
,
&
data
)
<
0
)
goto
on_error
;
cleanup:
regfree
(
&
preg
);
git_buf_free
(
&
buf
);
return
error
;
return
0
;
on_error:
regfree
(
&
preg
);
git_buf_free
(
&
buf
);
return
-
1
;
}
int
git_revwalk_push_glob
(
git_revwalk
*
walk
,
const
char
*
glob
)
...
...
@@ -391,37 +583,28 @@ int git_revwalk_hide_glob(git_revwalk *walk, const char *glob)
return
push_glob
(
walk
,
glob
,
1
);
}
static
int
push_head
(
git_revwalk
*
walk
,
int
hide
)
{
git_reference
*
ref
,
*
resolved
;
int
error
;
error
=
git_reference_lookup
(
&
ref
,
walk
->
repo
,
"HEAD"
);
if
(
error
<
GIT_SUCCESS
)
{
return
error
;
}
error
=
git_reference_resolve
(
&
resolved
,
ref
);
if
(
error
<
GIT_SUCCESS
)
{
return
error
;
}
git_reference_free
(
ref
);
error
=
push_commit
(
walk
,
git_reference_oid
(
resolved
),
hide
);
git_reference_free
(
resolved
);
return
error
;
}
int
git_revwalk_push_head
(
git_revwalk
*
walk
)
{
assert
(
walk
);
return
push_
head
(
walk
,
0
);
return
push_
ref
(
walk
,
GIT_HEAD_FILE
,
0
);
}
int
git_revwalk_hide_head
(
git_revwalk
*
walk
)
{
assert
(
walk
);
return
push_head
(
walk
,
1
);
return
push_ref
(
walk
,
GIT_HEAD_FILE
,
1
);
}
int
git_revwalk_push_ref
(
git_revwalk
*
walk
,
const
char
*
refname
)
{
assert
(
walk
&&
refname
);
return
push_ref
(
walk
,
refname
,
0
);
}
int
git_revwalk_hide_ref
(
git_revwalk
*
walk
,
const
char
*
refname
)
{
assert
(
walk
&&
refname
);
return
push_ref
(
walk
,
refname
,
1
);
}
static
int
revwalk_enqueue_timesort
(
git_revwalk
*
walk
,
commit_object
*
commit
)
...
...
@@ -440,16 +623,16 @@ static int revwalk_next_timesort(commit_object **object_out, git_revwalk *walk)
commit_object
*
next
;
while
((
next
=
git_pqueue_pop
(
&
walk
->
iterator_time
))
!=
NULL
)
{
if
((
error
=
process_commit_parents
(
walk
,
next
))
<
GIT_SUCCESS
)
return
git__rethrow
(
error
,
"Failed to load next revision"
)
;
if
((
error
=
process_commit_parents
(
walk
,
next
))
<
0
)
return
-
1
;
if
(
!
next
->
uninteresting
)
{
*
object_out
=
next
;
return
GIT_SUCCESS
;
return
0
;
}
}
return
git__throw
(
GIT_EREVWALKOVER
,
"Failed to load next revision"
)
;
return
GIT_EREVWALKOVER
;
}
static
int
revwalk_next_unsorted
(
commit_object
**
object_out
,
git_revwalk
*
walk
)
...
...
@@ -458,16 +641,16 @@ static int revwalk_next_unsorted(commit_object **object_out, git_revwalk *walk)
commit_object
*
next
;
while
((
next
=
commit_list_pop
(
&
walk
->
iterator_rand
))
!=
NULL
)
{
if
((
error
=
process_commit_parents
(
walk
,
next
))
<
GIT_SUCCESS
)
return
git__rethrow
(
error
,
"Failed to load next revision"
)
;
if
((
error
=
process_commit_parents
(
walk
,
next
))
<
0
)
return
-
1
;
if
(
!
next
->
uninteresting
)
{
*
object_out
=
next
;
return
GIT_SUCCESS
;
return
0
;
}
}
return
git__throw
(
GIT_EREVWALKOVER
,
"Failed to load next revision"
)
;
return
GIT_EREVWALKOVER
;
}
static
int
revwalk_next_toposort
(
commit_object
**
object_out
,
git_revwalk
*
walk
)
...
...
@@ -478,7 +661,7 @@ static int revwalk_next_toposort(commit_object **object_out, git_revwalk *walk)
for
(;;)
{
next
=
commit_list_pop
(
&
walk
->
iterator_topo
);
if
(
next
==
NULL
)
return
git__throw
(
GIT_EREVWALKOVER
,
"Failed to load next revision"
)
;
return
GIT_EREVWALKOVER
;
if
(
next
->
in_degree
>
0
)
{
next
->
topo_delay
=
1
;
...
...
@@ -490,41 +673,58 @@ static int revwalk_next_toposort(commit_object **object_out, git_revwalk *walk)
if
(
--
parent
->
in_degree
==
0
&&
parent
->
topo_delay
)
{
parent
->
topo_delay
=
0
;
commit_list_insert
(
parent
,
&
walk
->
iterator_topo
);
if
(
commit_list_insert
(
parent
,
&
walk
->
iterator_topo
)
==
NULL
)
return
-
1
;
}
}
*
object_out
=
next
;
return
GIT_SUCCESS
;
return
0
;
}
}
static
int
revwalk_next_reverse
(
commit_object
**
object_out
,
git_revwalk
*
walk
)
{
*
object_out
=
commit_list_pop
(
&
walk
->
iterator_reverse
);
return
*
object_out
?
GIT_SUCCESS
:
GIT_EREVWALKOVER
;
return
*
object_out
?
0
:
GIT_EREVWALKOVER
;
}
static
int
prepare_walk
(
git_revwalk
*
walk
)
{
int
error
;
commit_object
*
next
;
unsigned
int
i
;
commit_object
*
next
,
*
two
;
commit_list
*
bases
=
NULL
;
/* first figure out what the merge bases are */
if
(
merge_bases_many
(
&
bases
,
walk
,
walk
->
one
,
&
walk
->
twos
)
<
0
)
return
-
1
;
commit_list_free
(
&
bases
);
if
(
process_commit
(
walk
,
walk
->
one
,
walk
->
one
->
uninteresting
)
<
0
)
return
-
1
;
git_vector_foreach
(
&
walk
->
twos
,
i
,
two
)
{
if
(
process_commit
(
walk
,
two
,
two
->
uninteresting
)
<
0
)
return
-
1
;
}
if
(
walk
->
sorting
&
GIT_SORT_TOPOLOGICAL
)
{
unsigned
short
i
;
while
((
error
=
walk
->
get_next
(
&
next
,
walk
))
==
GIT_SUCCESS
)
{
while
((
error
=
walk
->
get_next
(
&
next
,
walk
))
==
0
)
{
for
(
i
=
0
;
i
<
next
->
out_degree
;
++
i
)
{
commit_object
*
parent
=
next
->
parents
[
i
];
parent
->
in_degree
++
;
}
commit_list_insert
(
next
,
&
walk
->
iterator_topo
);
if
(
commit_list_insert
(
next
,
&
walk
->
iterator_topo
)
==
NULL
)
return
-
1
;
}
if
(
error
!=
GIT_EREVWALKOVER
)
return
git__rethrow
(
error
,
"Failed to prepare revision walk"
)
;
return
-
1
;
walk
->
get_next
=
&
revwalk_next_toposort
;
}
...
...
@@ -532,16 +732,17 @@ static int prepare_walk(git_revwalk *walk)
if
(
walk
->
sorting
&
GIT_SORT_REVERSE
)
{
while
((
error
=
walk
->
get_next
(
&
next
,
walk
))
==
GIT_SUCCESS
)
commit_list_insert
(
next
,
&
walk
->
iterator_reverse
);
if
(
commit_list_insert
(
next
,
&
walk
->
iterator_reverse
)
==
NULL
)
return
-
1
;
if
(
error
!=
GIT_EREVWALKOVER
)
return
git__rethrow
(
error
,
"Failed to prepare revision walk"
)
;
return
-
1
;
walk
->
get_next
=
&
revwalk_next_reverse
;
}
walk
->
walking
=
1
;
return
GIT_SUCCESS
;
return
0
;
}
...
...
@@ -550,12 +751,10 @@ static int prepare_walk(git_revwalk *walk)
int
git_revwalk_new
(
git_revwalk
**
revwalk_out
,
git_repository
*
repo
)
{
int
error
;
git_revwalk
*
walk
;
walk
=
git__malloc
(
sizeof
(
git_revwalk
));
if
(
walk
==
NULL
)
return
GIT_ENOMEM
;
GITERR_CHECK_ALLOC
(
walk
);
memset
(
walk
,
0x0
,
sizeof
(
git_revwalk
));
...
...
@@ -565,11 +764,12 @@ int git_revwalk_new(git_revwalk **revwalk_out, git_repository *repo)
if
(
walk
->
commits
==
NULL
)
{
git__free
(
walk
);
return
GIT_ENOMEM
;
return
-
1
;
}
git_pqueue_init
(
&
walk
->
iterator_time
,
8
,
commit_time_cmp
);
git_vector_init
(
&
walk
->
memory_alloc
,
8
,
NULL
);
git_vector_init
(
&
walk
->
twos
,
4
,
NULL
);
alloc_chunk
(
walk
);
walk
->
get_next
=
&
revwalk_next_unsorted
;
...
...
@@ -577,14 +777,13 @@ int git_revwalk_new(git_revwalk **revwalk_out, git_repository *repo)
walk
->
repo
=
repo
;
error
=
git_repository_odb
(
&
walk
->
odb
,
repo
);
if
(
error
<
GIT_SUCCESS
)
{
if
(
git_repository_odb
(
&
walk
->
odb
,
repo
)
<
0
)
{
git_revwalk_free
(
walk
);
return
error
;
return
-
1
;
}
*
revwalk_out
=
walk
;
return
GIT_SUCCESS
;
return
0
;
}
void
git_revwalk_free
(
git_revwalk
*
walk
)
...
...
@@ -613,6 +812,7 @@ void git_revwalk_free(git_revwalk *walk)
git__free
(
git_vector_get
(
&
walk
->
memory_alloc
,
i
));
git_vector_free
(
&
walk
->
memory_alloc
);
git_vector_free
(
&
walk
->
twos
);
git__free
(
walk
);
}
...
...
@@ -648,8 +848,8 @@ int git_revwalk_next(git_oid *oid, git_revwalk *walk)
assert
(
walk
&&
oid
);
if
(
!
walk
->
walking
)
{
if
((
error
=
prepare_walk
(
walk
))
<
GIT_SUCCESS
)
return
git__rethrow
(
error
,
"Failed to load next revision"
)
;
if
((
error
=
prepare_walk
(
walk
))
<
0
)
return
-
1
;
}
error
=
walk
->
get_next
(
&
next
,
walk
);
...
...
@@ -659,11 +859,11 @@ int git_revwalk_next(git_oid *oid, git_revwalk *walk)
return
GIT_EREVWALKOVER
;
}
if
(
error
<
GIT_SUCCESS
)
return
git__rethrow
(
error
,
"Failed to load next revision"
)
;
if
(
error
<
0
)
return
-
1
;
git_oid_cpy
(
oid
,
&
next
->
oid
);
return
GIT_SUCCESS
;
return
0
;
}
void
git_revwalk_reset
(
git_revwalk
*
walk
)
...
...
tests-clar/revwalk/basic.c
View file @
d1f33156
...
...
@@ -148,14 +148,13 @@ void test_revwalk_basic__push_head(void)
cl_assert
(
i
==
7
);
}
void
test_revwalk_basic__push_head_hide_
glob
(
void
)
void
test_revwalk_basic__push_head_hide_
ref
(
void
)
{
int
i
=
0
;
git_oid
oid
;
cl_git_pass
(
git_revwalk_push_head
(
_walk
));
/* This is a hack, as we know this will only match the packed-test branch */
cl_git_pass
(
git_revwalk_hide_glob
(
_walk
,
"heads/packed-test*"
));
cl_git_pass
(
git_revwalk_hide_ref
(
_walk
,
"refs/heads/packed-test"
));
while
(
git_revwalk_next
(
&
oid
,
_walk
)
==
GIT_SUCCESS
)
{
i
++
;
...
...
@@ -164,3 +163,19 @@ void test_revwalk_basic__push_head_hide_glob(void)
/* git log HEAD --oneline --not refs/heads/packed-test | wc -l => 4 */
cl_assert
(
i
==
4
);
}
void
test_revwalk_basic__push_head_hide_ref_nobase
(
void
)
{
int
i
=
0
;
git_oid
oid
;
cl_git_pass
(
git_revwalk_push_head
(
_walk
));
cl_git_pass
(
git_revwalk_hide_ref
(
_walk
,
"refs/heads/packed"
));
while
(
git_revwalk_next
(
&
oid
,
_walk
)
==
GIT_SUCCESS
)
{
i
++
;
}
/* git log HEAD --oneline --not refs/heads/packed | wc -l => 7 */
cl_assert
(
i
==
7
);
}
tests-clar/revwalk/mergebase.c
0 → 100644
View file @
d1f33156
#include "clar_libgit2.h"
static
git_repository
*
_repo
;
void
test_revwalk_mergebase__initialize
(
void
)
{
cl_git_pass
(
git_repository_open
(
&
_repo
,
cl_fixture
(
"testrepo.git"
)));
}
void
test_revwalk_mergebase__cleanup
(
void
)
{
git_repository_free
(
_repo
);
}
void
test_revwalk_mergebase__single1
(
void
)
{
git_oid
result
,
one
,
two
,
expected
;
git_oid_fromstr
(
&
one
,
"c47800c7266a2be04c571c04d5a6614691ea99bd "
);
git_oid_fromstr
(
&
two
,
"9fd738e8f7967c078dceed8190330fc8648ee56a"
);
git_oid_fromstr
(
&
expected
,
"5b5b025afb0b4c913b4c338a42934a3863bf3644"
);
cl_git_pass
(
git_merge_base
(
&
result
,
_repo
,
&
one
,
&
two
));
cl_assert
(
git_oid_cmp
(
&
result
,
&
expected
)
==
0
);
}
void
test_revwalk_mergebase__single2
(
void
)
{
git_oid
result
,
one
,
two
,
expected
;
git_oid_fromstr
(
&
one
,
"763d71aadf09a7951596c9746c024e7eece7c7af"
);
git_oid_fromstr
(
&
two
,
"a65fedf39aefe402d3bb6e24df4d4f5fe4547750"
);
git_oid_fromstr
(
&
expected
,
"c47800c7266a2be04c571c04d5a6614691ea99bd"
);
cl_git_pass
(
git_merge_base
(
&
result
,
_repo
,
&
one
,
&
two
));
cl_assert
(
git_oid_cmp
(
&
result
,
&
expected
)
==
0
);
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment