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
0de2c4e3
Commit
0de2c4e3
authored
Feb 05, 2014
by
Ben Straub
Browse files
Options
Browse Files
Download
Plain Diff
Merge remote-tracking branch 'libgit2/development' into bs/more-reflog-stuff
parents
010cec3a
629ba7f1
Hide whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
548 additions
and
96 deletions
+548
-96
include/git2/revwalk.h
+12
-6
src/commit.c
+12
-28
src/merge.c
+4
-7
src/posix.h
+1
-12
src/revparse.c
+1
-2
src/revwalk.c
+42
-30
src/strnlen.h
+23
-0
src/util.h
+2
-2
tests/merge/workdir/dirty.c
+322
-0
tests/object/tree/write.c
+91
-9
tests/revwalk/basic.c
+38
-0
No files found.
include/git2/revwalk.h
View file @
0de2c4e3
...
...
@@ -87,7 +87,7 @@ GIT_EXTERN(void) git_revwalk_reset(git_revwalk *walker);
/**
* Mark a commit to start traversal from.
*
* The given OID must belong to a commit on the walked
* The given OID must belong to a commit
tish
on the walked
* repository.
*
* The given commit will be used as one of the roots
...
...
@@ -108,7 +108,10 @@ GIT_EXTERN(int) git_revwalk_push(git_revwalk *walk, const git_oid *id);
* pattern will be pushed to the revision walker.
*
* A leading 'refs/' is implied if not present as well as a trailing
* '/ *' if the glob lacks '?', '*' or '['.
* '/\*' if the glob lacks '?', '\*' or '['.
*
* Any references matching this glob which do not point to a
* committish will be ignored.
*
* @param walk the walker being used for the traversal
* @param glob the glob pattern references should match
...
...
@@ -127,7 +130,7 @@ GIT_EXTERN(int) git_revwalk_push_head(git_revwalk *walk);
/**
* Mark a commit (and its ancestors) uninteresting for the output.
*
* The given OID must belong to a commit on the walked
* The given OID must belong to a commit
tish
on the walked
* repository.
*
* The resolved commit and all its parents will be hidden from the
...
...
@@ -147,7 +150,10 @@ GIT_EXTERN(int) git_revwalk_hide(git_revwalk *walk, const git_oid *commit_id);
* revision walk.
*
* A leading 'refs/' is implied if not present as well as a trailing
* '/ *' if the glob lacks '?', '*' or '['.
* '/\*' if the glob lacks '?', '\*' or '['.
*
* Any references matching this glob which do not point to a
* committish will be ignored.
*
* @param walk the walker being used for the traversal
* @param glob the glob pattern references should match
...
...
@@ -166,7 +172,7 @@ 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.
* The reference must point to a commit
tish
.
*
* @param walk the walker being used for the traversal
* @param refname the reference to push
...
...
@@ -177,7 +183,7 @@ 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.
* The reference must point to a commit
tish
.
*
* @param walk the walker being used for the traversal
* @param refname the reference to hide
...
...
src/commit.c
View file @
0de2c4e3
...
...
@@ -183,33 +183,15 @@ int git_commit__parse(void *_commit, git_odb_object *odb_obj)
const
char
*
buffer_start
=
git_odb_object_data
(
odb_obj
),
*
buffer
;
const
char
*
buffer_end
=
buffer_start
+
git_odb_object_size
(
odb_obj
);
git_oid
parent_id
;
uint32_t
parent_count
=
0
;
size_t
header_len
;
/* find end-of-header (counting parents as we go) */
for
(
buffer
=
buffer_start
;
buffer
<
buffer_end
;
++
buffer
)
{
if
(
!
strncmp
(
"
\n\n
"
,
buffer
,
2
))
{
++
buffer
;
break
;
}
if
(
!
strncmp
(
"
\n
parent "
,
buffer
,
strlen
(
"
\n
parent "
)))
++
parent_count
;
}
header_len
=
buffer
-
buffer_start
;
commit
->
raw_header
=
git__strndup
(
buffer_start
,
header_len
);
GITERR_CHECK_ALLOC
(
commit
->
raw_header
);
buffer
=
buffer_start
;
/* point "buffer" to header data */
buffer
=
commit
->
raw_header
;
buffer_end
=
commit
->
raw_header
+
header_len
;
if
(
parent_count
<
1
)
parent_count
=
1
;
git_array_init_to_size
(
commit
->
parent_ids
,
parent_count
);
/* Allocate for one, which will allow not to realloc 90% of the time */
git_array_init_to_size
(
commit
->
parent_ids
,
1
);
GITERR_CHECK_ARRAY
(
commit
->
parent_ids
);
/* The tree is always the first field */
if
(
git_oid__parse
(
&
commit
->
tree_id
,
&
buffer
,
buffer_end
,
"tree "
)
<
0
)
goto
bad_buffer
;
...
...
@@ -240,6 +222,9 @@ int git_commit__parse(void *_commit, git_odb_object *odb_obj)
/* Parse add'l header entries */
while
(
buffer
<
buffer_end
)
{
const
char
*
eoln
=
buffer
;
if
(
buffer
[
-
1
]
==
'\n'
&&
buffer
[
0
]
==
'\n'
)
break
;
while
(
eoln
<
buffer_end
&&
*
eoln
!=
'\n'
)
++
eoln
;
...
...
@@ -255,13 +240,12 @@ int git_commit__parse(void *_commit, git_odb_object *odb_obj)
buffer
=
eoln
;
}
/* point "buffer" to data after header */
buffer
=
git_odb_object_data
(
odb_obj
);
buffer_end
=
buffer
+
git_odb_object_size
(
odb_obj
);
header_len
=
buffer
-
buffer_start
;
commit
->
raw_header
=
git__strndup
(
buffer_start
,
header_len
);
GITERR_CHECK_ALLOC
(
commit
->
raw_header
);
buffer
+=
header_len
;
if
(
*
buffer
==
'\n'
)
++
buffer
;
/* point "buffer" to data after header, +1 for the final LF */
buffer
=
buffer_start
+
header_len
+
1
;
/* extract commit message */
if
(
buffer
<=
buffer_end
)
{
...
...
src/merge.c
View file @
0de2c4e3
...
...
@@ -2330,7 +2330,7 @@ done:
static
int
merge_check_workdir
(
size_t
*
conflicts
,
git_repository
*
repo
,
git_index
*
index_new
,
git_vector
*
merged_paths
)
{
git_
tree
*
head_tree
=
NULL
;
git_
index
*
index_repo
=
NULL
;
git_diff
*
wd_diff_list
=
NULL
;
git_diff_options
opts
=
GIT_DIFF_OPTIONS_INIT
;
int
error
=
0
;
...
...
@@ -2341,9 +2341,6 @@ static int merge_check_workdir(size_t *conflicts, git_repository *repo, git_inde
opts
.
flags
|=
GIT_DIFF_INCLUDE_UNTRACKED
;
if
((
error
=
git_repository_head_tree
(
&
head_tree
,
repo
))
<
0
)
goto
done
;
/* Workdir changes may exist iff they do not conflict with changes that
* will be applied by the merge (including conflicts). Ensure that there
* are no changes in the workdir to these paths.
...
...
@@ -2351,13 +2348,13 @@ static int merge_check_workdir(size_t *conflicts, git_repository *repo, git_inde
opts
.
pathspec
.
count
=
merged_paths
->
length
;
opts
.
pathspec
.
strings
=
(
char
**
)
merged_paths
->
contents
;
if
((
error
=
git_diff_
tree_to_workdir
(
&
wd_diff_list
,
repo
,
head_tree
,
&
opts
))
<
0
)
if
((
error
=
git_diff_
index_to_workdir
(
&
wd_diff_list
,
repo
,
index_repo
,
&
opts
))
<
0
)
goto
done
;
*
conflicts
=
wd_diff_list
->
deltas
.
length
;
done
:
git_
tree_free
(
head_tree
);
git_
index_free
(
index_repo
);
git_diff_free
(
wd_diff_list
);
return
error
;
...
...
@@ -2400,7 +2397,7 @@ int git_merge__indexes(git_repository *repo, git_index *index_new)
/* Remove removed items from the index */
git_vector_foreach
(
&
paths
,
i
,
path
)
{
if
(
(
e
=
git_index_get_bypath
(
index_new
,
path
,
0
)
)
==
NULL
)
{
if
(
git_index_get_bypath
(
index_new
,
path
,
0
)
==
NULL
)
{
if
((
error
=
git_index_remove
(
index_repo
,
path
,
0
))
<
0
&&
error
!=
GIT_ENOTFOUND
)
goto
done
;
...
...
src/posix.h
View file @
0de2c4e3
...
...
@@ -89,18 +89,7 @@ extern struct tm * p_gmtime_r (const time_t *timer, struct tm *result);
# include "unix/posix.h"
#endif
#if defined(__MINGW32__) || defined(__sun) || defined(__APPLE__)
# define NO_STRNLEN
#endif
#ifdef NO_STRNLEN
GIT_INLINE
(
size_t
)
p_strnlen
(
const
char
*
s
,
size_t
maxlen
)
{
const
char
*
end
=
memchr
(
s
,
0
,
maxlen
);
return
end
?
(
size_t
)(
end
-
s
)
:
maxlen
;
}
#else
# define p_strnlen strnlen
#endif
#include "strnlen.h"
#ifdef NO_READDIR_R
# include <dirent.h>
...
...
src/revparse.c
View file @
0de2c4e3
...
...
@@ -490,8 +490,7 @@ static int handle_grep_syntax(git_object **out, git_repository *repo, const git_
git_revwalk_sorting
(
walk
,
GIT_SORT_TIME
);
if
(
spec_oid
==
NULL
)
{
// TODO: @carlosmn: The glob should be refs/* but this makes git_revwalk_next() fails
if
((
error
=
git_revwalk_push_glob
(
walk
,
GIT_REFS_HEADS_DIR
"*"
))
<
0
)
if
((
error
=
git_revwalk_push_glob
(
walk
,
"refs/*"
))
<
0
)
goto
cleanup
;
}
else
if
((
error
=
git_revwalk_push
(
walk
,
spec_oid
))
<
0
)
goto
cleanup
;
...
...
src/revwalk.c
View file @
0de2c4e3
...
...
@@ -110,25 +110,34 @@ static int process_commit_parents(git_revwalk *walk, git_commit_list_node *commi
return
error
;
}
static
int
push_commit
(
git_revwalk
*
walk
,
const
git_oid
*
oid
,
int
uninteresting
)
static
int
push_commit
(
git_revwalk
*
walk
,
const
git_oid
*
oid
,
int
uninteresting
,
int
from_glob
)
{
git_oid
commit_id
;
int
error
;
git_object
*
obj
;
git_otype
type
;
git_object
*
obj
,
*
oobj
;
git_commit_list_node
*
commit
;
if
((
error
=
git_object_lookup
(
&
obj
,
walk
->
repo
,
oid
,
GIT_OBJ_ANY
))
<
0
)
if
((
error
=
git_object_lookup
(
&
o
o
bj
,
walk
->
repo
,
oid
,
GIT_OBJ_ANY
))
<
0
)
return
error
;
type
=
git_object_type
(
obj
);
git_object_free
(
obj
);
error
=
git_object_peel
(
&
obj
,
oobj
,
GIT_OBJ_COMMIT
);
git_object_free
(
oobj
);
if
(
error
==
GIT_ENOTFOUND
)
{
/* If this comes from e.g. push_glob("tags"), ignore this */
if
(
from_glob
)
return
0
;
if
(
type
!=
GIT_OBJ_COMMIT
)
{
giterr_set
(
GITERR_INVALID
,
"Object is no commit object"
);
giterr_set
(
GITERR_INVALID
,
"Object is not a committish"
);
return
-
1
;
}
if
(
error
<
0
)
return
error
;
git_oid_cpy
(
&
commit_id
,
git_object_id
(
obj
));
git_object_free
(
obj
);
commit
=
git_revwalk__commit_lookup
(
walk
,
o
id
);
commit
=
git_revwalk__commit_lookup
(
walk
,
&
commit_
id
);
if
(
commit
==
NULL
)
return
-
1
;
/* error already reported by failed lookup */
...
...
@@ -146,24 +155,24 @@ static int push_commit(git_revwalk *walk, const git_oid *oid, int uninteresting)
int
git_revwalk_push
(
git_revwalk
*
walk
,
const
git_oid
*
oid
)
{
assert
(
walk
&&
oid
);
return
push_commit
(
walk
,
oid
,
0
);
return
push_commit
(
walk
,
oid
,
0
,
false
);
}
int
git_revwalk_hide
(
git_revwalk
*
walk
,
const
git_oid
*
oid
)
{
assert
(
walk
&&
oid
);
return
push_commit
(
walk
,
oid
,
1
);
return
push_commit
(
walk
,
oid
,
1
,
false
);
}
static
int
push_ref
(
git_revwalk
*
walk
,
const
char
*
refname
,
int
hide
)
static
int
push_ref
(
git_revwalk
*
walk
,
const
char
*
refname
,
int
hide
,
int
from_glob
)
{
git_oid
oid
;
if
(
git_reference_name_to_id
(
&
oid
,
walk
->
repo
,
refname
)
<
0
)
return
-
1
;
return
push_commit
(
walk
,
&
oid
,
hide
);
return
push_commit
(
walk
,
&
oid
,
hide
,
from_glob
);
}
struct
push_cb_data
{
...
...
@@ -171,17 +180,12 @@ struct push_cb_data {
int
hide
;
};
static
int
push_glob_cb
(
const
char
*
refname
,
void
*
data_
)
{
struct
push_cb_data
*
data
=
(
struct
push_cb_data
*
)
data_
;
return
push_ref
(
data
->
walk
,
refname
,
data
->
hide
);
}
static
int
push_glob
(
git_revwalk
*
walk
,
const
char
*
glob
,
int
hide
)
{
int
error
=
0
;
git_buf
buf
=
GIT_BUF_INIT
;
struct
push_cb_data
data
;
git_reference
*
ref
;
git_reference_iterator
*
iter
;
size_t
wildcard
;
assert
(
walk
&&
glob
);
...
...
@@ -199,12 +203,20 @@ static int push_glob(git_revwalk *walk, const char *glob, int hide)
if
(
!
glob
[
wildcard
])
git_buf_put
(
&
buf
,
"/*"
,
2
);
data
.
walk
=
walk
;
data
.
hide
=
hide
;
if
((
error
=
git_reference_iterator_glob_new
(
&
iter
,
walk
->
repo
,
buf
.
ptr
))
<
0
)
goto
out
;
error
=
git_reference_foreach_glob
(
walk
->
repo
,
git_buf_cstr
(
&
buf
),
push_glob_cb
,
&
data
);
while
((
error
=
git_reference_next
(
&
ref
,
iter
))
==
0
)
{
error
=
push_ref
(
walk
,
git_reference_name
(
ref
),
hide
,
true
);
git_reference_free
(
ref
);
if
(
error
<
0
)
break
;
}
git_reference_iterator_free
(
iter
);
if
(
error
==
GIT_ITEROVER
)
error
=
0
;
out:
git_buf_free
(
&
buf
);
return
error
;
}
...
...
@@ -224,19 +236,19 @@ int git_revwalk_hide_glob(git_revwalk *walk, const char *glob)
int
git_revwalk_push_head
(
git_revwalk
*
walk
)
{
assert
(
walk
);
return
push_ref
(
walk
,
GIT_HEAD_FILE
,
0
);
return
push_ref
(
walk
,
GIT_HEAD_FILE
,
0
,
false
);
}
int
git_revwalk_hide_head
(
git_revwalk
*
walk
)
{
assert
(
walk
);
return
push_ref
(
walk
,
GIT_HEAD_FILE
,
1
);
return
push_ref
(
walk
,
GIT_HEAD_FILE
,
1
,
false
);
}
int
git_revwalk_push_ref
(
git_revwalk
*
walk
,
const
char
*
refname
)
{
assert
(
walk
&&
refname
);
return
push_ref
(
walk
,
refname
,
0
);
return
push_ref
(
walk
,
refname
,
0
,
false
);
}
int
git_revwalk_push_range
(
git_revwalk
*
walk
,
const
char
*
range
)
...
...
@@ -253,10 +265,10 @@ int git_revwalk_push_range(git_revwalk *walk, const char *range)
return
GIT_EINVALIDSPEC
;
}
if
((
error
=
push_commit
(
walk
,
git_object_id
(
revspec
.
from
),
1
)))
if
((
error
=
push_commit
(
walk
,
git_object_id
(
revspec
.
from
),
1
,
false
)))
goto
out
;
error
=
push_commit
(
walk
,
git_object_id
(
revspec
.
to
),
0
);
error
=
push_commit
(
walk
,
git_object_id
(
revspec
.
to
),
0
,
false
);
out:
git_object_free
(
revspec
.
from
);
...
...
@@ -267,7 +279,7 @@ out:
int
git_revwalk_hide_ref
(
git_revwalk
*
walk
,
const
char
*
refname
)
{
assert
(
walk
&&
refname
);
return
push_ref
(
walk
,
refname
,
1
);
return
push_ref
(
walk
,
refname
,
1
,
false
);
}
static
int
revwalk_enqueue_timesort
(
git_revwalk
*
walk
,
git_commit_list_node
*
commit
)
...
...
src/strnlen.h
0 → 100644
View file @
0de2c4e3
/*
* Copyright (C) the libgit2 contributors. All rights reserved.
*
* 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_strlen_h__
#define INCLUDE_strlen_h__
#if defined(__MINGW32__) || defined(__sun) || defined(__APPLE__)
# define NO_STRNLEN
#endif
#ifdef NO_STRNLEN
GIT_INLINE
(
size_t
)
p_strnlen
(
const
char
*
s
,
size_t
maxlen
)
{
const
char
*
end
=
memchr
(
s
,
0
,
maxlen
);
return
end
?
(
size_t
)(
end
-
s
)
:
maxlen
;
}
#else
# define p_strnlen strnlen
#endif
#endif
src/util.h
View file @
0de2c4e3
...
...
@@ -8,6 +8,7 @@
#define INCLUDE_util_h__
#include "common.h"
#include "strnlen.h"
#define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0]))
#define bitsizeof(x) (CHAR_BIT * sizeof(x))
...
...
@@ -50,8 +51,7 @@ GIT_INLINE(char *) git__strndup(const char *str, size_t n)
size_t
length
=
0
;
char
*
ptr
;
while
(
length
<
n
&&
str
[
length
])
++
length
;
length
=
p_strnlen
(
str
,
n
);
ptr
=
(
char
*
)
git__malloc
(
length
+
1
);
...
...
tests/merge/workdir/dirty.c
0 → 100644
View file @
0de2c4e3
#include "clar_libgit2.h"
#include "git2/merge.h"
#include "buffer.h"
#include "merge.h"
#include "../merge_helpers.h"
#include "posix.h"
#define TEST_REPO_PATH "merge-resolve"
#define MERGE_BRANCH_OID "7cb63eed597130ba4abb87b3e544b85021905520"
#define AUTOMERGEABLE_MERGED_FILE \
"this file is changed in master\n" \
"this file is automergeable\n" \
"this file is automergeable\n" \
"this file is automergeable\n" \
"this file is automergeable\n" \
"this file is automergeable\n" \
"this file is automergeable\n" \
"this file is automergeable\n" \
"this file is changed in branch\n"
#define CHANGED_IN_BRANCH_FILE \
"changed in branch\n"
static
git_repository
*
repo
;
static
git_index
*
repo_index
;
static
char
*
unaffected
[][
4
]
=
{
{
"added-in-master.txt"
,
NULL
},
{
"changed-in-master.txt"
,
NULL
},
{
"unchanged.txt"
,
NULL
},
{
"added-in-master.txt"
,
"changed-in-master.txt"
,
NULL
},
{
"added-in-master.txt"
,
"unchanged.txt"
,
NULL
},
{
"changed-in-master.txt"
,
"unchanged.txt"
,
NULL
},
{
"added-in-master.txt"
,
"changed-in-master.txt"
,
"unchanged.txt"
,
NULL
},
{
"new_file.txt"
,
NULL
},
{
"new_file.txt"
,
"unchanged.txt"
,
NULL
},
{
NULL
},
};
static
char
*
affected
[][
5
]
=
{
{
"automergeable.txt"
,
NULL
},
{
"changed-in-branch.txt"
,
NULL
},
{
"conflicting.txt"
,
NULL
},
{
"removed-in-branch.txt"
,
NULL
},
{
"automergeable.txt"
,
"changed-in-branch.txt"
,
NULL
},
{
"automergeable.txt"
,
"conflicting.txt"
,
NULL
},
{
"automergeable.txt"
,
"removed-in-branch.txt"
,
NULL
},
{
"changed-in-branch.txt"
,
"conflicting.txt"
,
NULL
},
{
"changed-in-branch.txt"
,
"removed-in-branch.txt"
,
NULL
},
{
"conflicting.txt"
,
"removed-in-branch.txt"
,
NULL
},
{
"automergeable.txt"
,
"changed-in-branch.txt"
,
"conflicting.txt"
,
NULL
},
{
"automergeable.txt"
,
"changed-in-branch.txt"
,
"removed-in-branch.txt"
,
NULL
},
{
"automergeable.txt"
,
"conflicting.txt"
,
"removed-in-branch.txt"
,
NULL
},
{
"changed-in-branch.txt"
,
"conflicting.txt"
,
"removed-in-branch.txt"
,
NULL
},
{
"automergeable.txt"
,
"changed-in-branch.txt"
,
"conflicting.txt"
,
"removed-in-branch.txt"
,
NULL
},
{
NULL
},
};
static
char
*
result_contents
[
4
][
6
]
=
{
{
"automergeable.txt"
,
AUTOMERGEABLE_MERGED_FILE
,
NULL
,
NULL
},
{
"changed-in-branch.txt"
,
CHANGED_IN_BRANCH_FILE
,
NULL
,
NULL
},
{
"automergeable.txt"
,
AUTOMERGEABLE_MERGED_FILE
,
"changed-in-branch.txt"
,
CHANGED_IN_BRANCH_FILE
,
NULL
,
NULL
},
{
NULL
}
};
void
test_merge_workdir_dirty__initialize
(
void
)
{
repo
=
cl_git_sandbox_init
(
TEST_REPO_PATH
);
git_repository_index
(
&
repo_index
,
repo
);
}
void
test_merge_workdir_dirty__cleanup
(
void
)
{
git_index_free
(
repo_index
);
cl_git_sandbox_cleanup
();
}
static
void
set_core_autocrlf_to
(
git_repository
*
repo
,
bool
value
)
{
git_config
*
cfg
;
cl_git_pass
(
git_repository_config
(
&
cfg
,
repo
));
cl_git_pass
(
git_config_set_bool
(
cfg
,
"core.autocrlf"
,
value
));
git_config_free
(
cfg
);
}
static
int
merge_branch
(
git_merge_result
**
result
,
int
merge_file_favor
,
int
checkout_strategy
)
{
git_oid
their_oids
[
1
];
git_merge_head
*
their_heads
[
1
];
git_merge_opts
opts
=
GIT_MERGE_OPTS_INIT
;
int
error
;
cl_git_pass
(
git_oid_fromstr
(
&
their_oids
[
0
],
MERGE_BRANCH_OID
));
cl_git_pass
(
git_merge_head_from_id
(
&
their_heads
[
0
],
repo
,
&
their_oids
[
0
]));
opts
.
merge_tree_opts
.
file_favor
=
merge_file_favor
;
opts
.
checkout_opts
.
checkout_strategy
=
checkout_strategy
;
error
=
git_merge
(
result
,
repo
,
(
const
git_merge_head
**
)
their_heads
,
1
,
&
opts
);
git_merge_head_free
(
their_heads
[
0
]);
return
error
;
}
static
void
write_files
(
char
*
files
[])
{
char
*
filename
;
git_buf
path
=
GIT_BUF_INIT
,
content
=
GIT_BUF_INIT
;
size_t
i
;
for
(
i
=
0
,
filename
=
files
[
i
];
filename
;
filename
=
files
[
++
i
])
{
git_buf_clear
(
&
path
);
git_buf_clear
(
&
content
);
git_buf_printf
(
&
path
,
"%s/%s"
,
TEST_REPO_PATH
,
filename
);
git_buf_printf
(
&
content
,
"This is a dirty file in the working directory!
\n\n
"
"It will not be staged! Its filename is %s.
\n
"
,
filename
);
cl_git_mkfile
(
path
.
ptr
,
content
.
ptr
);
}
git_buf_free
(
&
path
);
git_buf_free
(
&
content
);
}
static
void
hack_index
(
char
*
files
[])
{
char
*
filename
;
struct
stat
statbuf
;
git_buf
path
=
GIT_BUF_INIT
;
git_index_entry
*
entry
;
size_t
i
;
/* Update the index to suggest that checkout placed these files on
* disk, keeping the object id but updating the cache, which will
* emulate a Git implementation's different filter.
*/
for
(
i
=
0
,
filename
=
files
[
i
];
filename
;
filename
=
files
[
++
i
])
{
git_buf_clear
(
&
path
);
cl_assert
(
entry
=
(
git_index_entry
*
)
git_index_get_bypath
(
repo_index
,
filename
,
0
));
cl_git_pass
(
git_buf_printf
(
&
path
,
"%s/%s"
,
TEST_REPO_PATH
,
filename
));
cl_git_pass
(
p_stat
(
path
.
ptr
,
&
statbuf
));
entry
->
ctime
.
seconds
=
(
git_time_t
)
statbuf
.
st_ctime
;
entry
->
ctime
.
nanoseconds
=
0
;
entry
->
mtime
.
seconds
=
(
git_time_t
)
statbuf
.
st_mtime
;
entry
->
mtime
.
nanoseconds
=
0
;
entry
->
dev
=
statbuf
.
st_dev
;
entry
->
ino
=
statbuf
.
st_ino
;
entry
->
uid
=
statbuf
.
st_uid
;
entry
->
gid
=
statbuf
.
st_gid
;
entry
->
file_size
=
statbuf
.
st_size
;
}
git_buf_free
(
&
path
);
}
static
void
stage_random_files
(
char
*
files
[])
{
char
*
filename
;
size_t
i
;
write_files
(
files
);
for
(
i
=
0
,
filename
=
files
[
i
];
filename
;
filename
=
files
[
++
i
])
cl_git_pass
(
git_index_add_bypath
(
repo_index
,
filename
));
}
static
void
stage_content
(
char
*
content
[])
{
git_reference
*
head
;
git_object
*
head_object
;
git_merge_result
*
result
=
NULL
;
git_buf
path
=
GIT_BUF_INIT
;
char
*
filename
,
*
text
;
size_t
i
;
cl_git_pass
(
git_repository_head
(
&
head
,
repo
));
cl_git_pass
(
git_reference_peel
(
&
head_object
,
head
,
GIT_OBJ_COMMIT
));
cl_git_pass
(
git_reset
(
repo
,
head_object
,
GIT_RESET_HARD
));
for
(
i
=
0
,
filename
=
content
[
i
],
text
=
content
[
++
i
];
filename
&&
text
;
filename
=
content
[
++
i
],
text
=
content
[
++
i
])
{
git_buf_clear
(
&
path
);
cl_git_pass
(
git_buf_printf
(
&
path
,
"%s/%s"
,
TEST_REPO_PATH
,
filename
));
cl_git_mkfile
(
path
.
ptr
,
text
);
cl_git_pass
(
git_index_add_bypath
(
repo_index
,
filename
));
}
git_merge_result_free
(
result
);
git_object_free
(
head_object
);
git_reference_free
(
head
);
git_buf_free
(
&
path
);
}
static
int
merge_dirty_files
(
char
*
dirty_files
[])
{
git_reference
*
head
;
git_object
*
head_object
;
git_merge_result
*
result
=
NULL
;
int
error
;
cl_git_pass
(
git_repository_head
(
&
head
,
repo
));
cl_git_pass
(
git_reference_peel
(
&
head_object
,
head
,
GIT_OBJ_COMMIT
));
cl_git_pass
(
git_reset
(
repo
,
head_object
,
GIT_RESET_HARD
));
write_files
(
dirty_files
);
error
=
merge_branch
(
&
result
,
0
,
0
);
git_merge_result_free
(
result
);
git_object_free
(
head_object
);
git_reference_free
(
head
);
return
error
;
}
static
int
merge_differently_filtered_files
(
char
*
files
[])
{
git_reference
*
head
;
git_object
*
head_object
;
git_merge_result
*
result
=
NULL
;
int
error
;
cl_git_pass
(
git_repository_head
(
&
head
,
repo
));
cl_git_pass
(
git_reference_peel
(
&
head_object
,
head
,
GIT_OBJ_COMMIT
));
cl_git_pass
(
git_reset
(
repo
,
head_object
,
GIT_RESET_HARD
));
write_files
(
files
);
hack_index
(
files
);
cl_git_pass
(
git_index_write
(
repo_index
));
error
=
merge_branch
(
&
result
,
0
,
0
);
git_merge_result_free
(
result
);
git_object_free
(
head_object
);
git_reference_free
(
head
);
return
error
;
}
static
int
merge_staged_files
(
char
*
staged_files
[])
{
git_merge_result
*
result
=
NULL
;
int
error
;
stage_random_files
(
staged_files
);
error
=
merge_branch
(
&
result
,
0
,
0
);
git_merge_result_free
(
result
);
return
error
;
}
void
test_merge_workdir_dirty__unaffected_dirty_files_allowed
(
void
)
{
char
**
files
;
size_t
i
;
for
(
i
=
0
,
files
=
unaffected
[
i
];
files
[
0
];
files
=
unaffected
[
++
i
])
cl_git_pass
(
merge_dirty_files
(
files
));
}
void
test_merge_workdir_dirty__affected_dirty_files_disallowed
(
void
)
{
char
**
files
;
size_t
i
;
for
(
i
=
0
,
files
=
affected
[
i
];
files
[
0
];
files
=
affected
[
++
i
])
cl_git_fail
(
merge_dirty_files
(
files
));
}
void
test_merge_workdir_dirty__staged_files_in_index_disallowed
(
void
)
{
char
**
files
;
size_t
i
;
for
(
i
=
0
,
files
=
unaffected
[
i
];
files
[
0
];
files
=
unaffected
[
++
i
])
cl_git_fail
(
merge_staged_files
(
files
));
for
(
i
=
0
,
files
=
affected
[
i
];
files
[
0
];
files
=
affected
[
++
i
])
cl_git_fail
(
merge_staged_files
(
files
));
}
void
test_merge_workdir_dirty__identical_staged_files_allowed
(
void
)
{
git_merge_result
*
result
;
char
**
content
;
size_t
i
;
set_core_autocrlf_to
(
repo
,
false
);
for
(
i
=
0
,
content
=
result_contents
[
i
];
content
[
0
];
content
=
result_contents
[
++
i
])
{
stage_content
(
content
);
git_index_write
(
repo_index
);
cl_git_pass
(
merge_branch
(
&
result
,
0
,
0
));
git_merge_result_free
(
result
);
}
}
void
test_merge_workdir_dirty__honors_cache
(
void
)
{
char
**
files
;
size_t
i
;
for
(
i
=
0
,
files
=
affected
[
i
];
files
[
0
];
files
=
affected
[
++
i
])
cl_git_pass
(
merge_differently_filtered_files
(
files
));
}
tests/object/tree/write.c
View file @
0de2c4e3
...
...
@@ -9,7 +9,7 @@ static const char *third_tree = "eb86d8b81d6adbd5290a935d6c9976882de98488";
static
git_repository
*
g_repo
;
/
/ Fixture setup and teardown
/
* Fixture setup and teardown */
void
test_object_tree_write__initialize
(
void
)
{
g_repo
=
cl_git_sandbox_init
(
"testrepo"
);
...
...
@@ -22,7 +22,7 @@ void test_object_tree_write__cleanup(void)
void
test_object_tree_write__from_memory
(
void
)
{
// write a tree from a memory
/* write a tree from a memory */
git_treebuilder
*
builder
;
git_tree
*
tree
;
git_oid
id
,
bid
,
rid
,
id2
;
...
...
@@ -31,7 +31,9 @@ void test_object_tree_write__from_memory(void)
git_oid_fromstr
(
&
id2
,
second_tree
);
git_oid_fromstr
(
&
bid
,
blob_oid
);
//create a second tree from first tree using `git_treebuilder_insert` on REPOSITORY_FOLDER.
/* create a second tree from first tree using `git_treebuilder_insert`
* on REPOSITORY_FOLDER.
*/
cl_git_pass
(
git_tree_lookup
(
&
tree
,
g_repo
,
&
id
));
cl_git_pass
(
git_treebuilder_create
(
&
builder
,
tree
));
...
...
@@ -61,7 +63,7 @@ void test_object_tree_write__from_memory(void)
void
test_object_tree_write__subtree
(
void
)
{
// write a hierarchical tree from a memory
/* write a hierarchical tree from a memory */
git_treebuilder
*
builder
;
git_tree
*
tree
;
git_oid
id
,
bid
,
subtree_id
,
id2
,
id3
;
...
...
@@ -72,25 +74,25 @@ void test_object_tree_write__subtree(void)
git_oid_fromstr
(
&
id3
,
third_tree
);
git_oid_fromstr
(
&
bid
,
blob_oid
);
/
/create subtree
/
* create subtree */
cl_git_pass
(
git_treebuilder_create
(
&
builder
,
NULL
));
cl_git_pass
(
git_treebuilder_insert
(
NULL
,
builder
,
"new.txt"
,
&
bid
,
GIT_FILEMODE_BLOB
));
/
/-V536
NULL
,
builder
,
"new.txt"
,
&
bid
,
GIT_FILEMODE_BLOB
));
/
* -V536 */
cl_git_pass
(
git_treebuilder_write
(
&
subtree_id
,
g_repo
,
builder
));
git_treebuilder_free
(
builder
);
/
/ create parent tree
/
* create parent tree */
cl_git_pass
(
git_tree_lookup
(
&
tree
,
g_repo
,
&
id
));
cl_git_pass
(
git_treebuilder_create
(
&
builder
,
tree
));
cl_git_pass
(
git_treebuilder_insert
(
NULL
,
builder
,
"new"
,
&
subtree_id
,
GIT_FILEMODE_TREE
));
/
/-V536
NULL
,
builder
,
"new"
,
&
subtree_id
,
GIT_FILEMODE_TREE
));
/
* -V536 */
cl_git_pass
(
git_treebuilder_write
(
&
id_hiearar
,
g_repo
,
builder
));
git_treebuilder_free
(
builder
);
git_tree_free
(
tree
);
cl_assert
(
git_oid_cmp
(
&
id_hiearar
,
&
id3
)
==
0
);
/
/ check data is correct
/
* check data is correct */
cl_git_pass
(
git_tree_lookup
(
&
tree
,
g_repo
,
&
id_hiearar
));
cl_assert
(
2
==
git_tree_entrycount
(
tree
));
git_tree_free
(
tree
);
...
...
@@ -314,3 +316,83 @@ void test_object_tree_write__filtering(void)
git_tree_free
(
tree
);
}
void
test_object_tree_write__cruel_paths
(
void
)
{
static
const
char
*
the_paths
[]
=
{
"C:
\\
"
,
" : * ?
\"
\n
< > |"
,
"a
\\
b"
,
"
\\\\
b
\a
"
,
":
\\
"
,
"COM1"
,
"foo.aux"
,
REP1024
(
"1234"
),
/* 4096 char string */
REP1024
(
"12345678"
),
/* 8192 char string */
"
\xC5\xAA\x6E\xC4\xAD\x63\xC5\x8D\x64\x65\xCC\xBD
"
,
/* Ūnĭcōde̽ */
NULL
};
git_treebuilder
*
builder
;
git_tree
*
tree
;
git_oid
id
,
bid
,
subid
;
const
char
**
scan
;
int
count
=
0
,
i
,
j
;
git_tree_entry
*
te
;
git_oid_fromstr
(
&
bid
,
blob_oid
);
/* create tree */
cl_git_pass
(
git_treebuilder_create
(
&
builder
,
NULL
));
for
(
scan
=
the_paths
;
*
scan
;
++
scan
)
{
cl_git_pass
(
git_treebuilder_insert
(
NULL
,
builder
,
*
scan
,
&
bid
,
GIT_FILEMODE_BLOB
));
count
++
;
}
cl_git_pass
(
git_treebuilder_write
(
&
id
,
g_repo
,
builder
));
git_treebuilder_free
(
builder
);
/* check data is correct */
cl_git_pass
(
git_tree_lookup
(
&
tree
,
g_repo
,
&
id
));
cl_assert_equal_i
(
count
,
git_tree_entrycount
(
tree
));
for
(
scan
=
the_paths
;
*
scan
;
++
scan
)
{
const
git_tree_entry
*
cte
=
git_tree_entry_byname
(
tree
,
*
scan
);
cl_assert
(
cte
!=
NULL
);
cl_assert_equal_s
(
*
scan
,
git_tree_entry_name
(
cte
));
}
for
(
scan
=
the_paths
;
*
scan
;
++
scan
)
{
cl_git_pass
(
git_tree_entry_bypath
(
&
te
,
tree
,
*
scan
));
cl_assert_equal_s
(
*
scan
,
git_tree_entry_name
(
te
));
git_tree_entry_free
(
te
);
}
git_tree_free
(
tree
);
/* let's try longer paths */
cl_git_pass
(
git_treebuilder_create
(
&
builder
,
NULL
));
for
(
scan
=
the_paths
;
*
scan
;
++
scan
)
{
cl_git_pass
(
git_treebuilder_insert
(
NULL
,
builder
,
*
scan
,
&
id
,
GIT_FILEMODE_TREE
));
}
cl_git_pass
(
git_treebuilder_write
(
&
subid
,
g_repo
,
builder
));
git_treebuilder_free
(
builder
);
/* check data is correct */
cl_git_pass
(
git_tree_lookup
(
&
tree
,
g_repo
,
&
subid
));
cl_assert_equal_i
(
count
,
git_tree_entrycount
(
tree
));
for
(
i
=
0
;
i
<
count
;
++
i
)
{
for
(
j
=
0
;
j
<
count
;
++
j
)
{
git_buf
b
=
GIT_BUF_INIT
;
cl_git_pass
(
git_buf_joinpath
(
&
b
,
the_paths
[
i
],
the_paths
[
j
]));
cl_git_pass
(
git_tree_entry_bypath
(
&
te
,
tree
,
b
.
ptr
));
cl_assert_equal_s
(
the_paths
[
j
],
git_tree_entry_name
(
te
));
git_tree_entry_free
(
te
);
git_buf_free
(
&
b
);
}
}
git_tree_free
(
tree
);
}
tests/revwalk/basic.c
View file @
0de2c4e3
...
...
@@ -252,3 +252,41 @@ void test_revwalk_basic__push_range(void)
cl_git_pass
(
git_revwalk_push_range
(
_walk
,
"9fd738e~2..9fd738e"
));
cl_git_pass
(
test_walk_only
(
_walk
,
commit_sorting_segment
,
1
));
}
void
test_revwalk_basic__push_mixed
(
void
)
{
git_oid
oid
;
int
i
=
0
;
revwalk_basic_setup_walk
(
NULL
);
git_revwalk_reset
(
_walk
);
git_revwalk_sorting
(
_walk
,
0
);
cl_git_pass
(
git_revwalk_push_glob
(
_walk
,
"tags"
));
while
(
git_revwalk_next
(
&
oid
,
_walk
)
==
0
)
{
i
++
;
}
/* git rev-list --count --glob=tags #=> 9 */
cl_assert_equal_i
(
9
,
i
);
}
void
test_revwalk_basic__push_all
(
void
)
{
git_oid
oid
;
int
i
=
0
;
revwalk_basic_setup_walk
(
NULL
);
git_revwalk_reset
(
_walk
);
git_revwalk_sorting
(
_walk
,
0
);
cl_git_pass
(
git_revwalk_push_glob
(
_walk
,
"*"
));
while
(
git_revwalk_next
(
&
oid
,
_walk
)
==
0
)
{
i
++
;
}
/* git rev-list --count --all #=> 15 */
cl_assert_equal_i
(
15
,
i
);
}
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