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
43b67d49
Commit
43b67d49
authored
Jul 27, 2012
by
Vicent Marti
Browse files
Options
Browse Files
Download
Plain Diff
Merge remote-tracking branch 'nulltoken/topic/reflog-delete' into development
parents
c0c39025
c3be5c5a
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
453 additions
and
167 deletions
+453
-167
include/git2/reflog.h
+36
-8
src/reflog.c
+219
-102
src/reflog.h
+3
-0
tests-clar/refs/reflog/drop.c
+130
-0
tests-clar/refs/reflog/reflog.c
+65
-57
No files found.
include/git2/reflog.h
View file @
43b67d49
...
...
@@ -23,6 +23,10 @@ GIT_BEGIN_DECL
/**
* Read the reflog for the given reference
*
* If there is no reflog file for the given
* reference yet, an empty reflog object will
* be returned.
*
* The reflog must be freed manually by using
* git_reflog_free().
*
...
...
@@ -33,22 +37,26 @@ GIT_BEGIN_DECL
GIT_EXTERN
(
int
)
git_reflog_read
(
git_reflog
**
reflog
,
git_reference
*
ref
);
/**
* Write a new reflog for the given reference
*
* If there is no reflog file for the given
* reference yet, it will be created.
* Write an existing in-memory reflog object back to disk
* using an atomic file lock.
*
* `oid_old` may be NULL in case it's a new reference.
* @param reflog an existing reflog object
* @return 0 or an error code
*/
GIT_EXTERN
(
int
)
git_reflog_write
(
git_reflog
*
reflog
);
/**
* Add a new entry to the reflog.
*
* `msg` is optional and can be NULL.
*
* @param ref
the changed reference
* @param
oid_old the OID the reference was
pointing to
* @param ref
log an existing reflog object
* @param
new_oid the OID the reference is now
pointing to
* @param committer the signature of the committer
* @param msg the reflog message
* @return 0 or an error code
*/
GIT_EXTERN
(
int
)
git_reflog_
write
(
git_reference
*
ref
,
const
git_oid
*
oid_ol
d
,
const
git_signature
*
committer
,
const
char
*
msg
);
GIT_EXTERN
(
int
)
git_reflog_
append
(
git_reflog
*
reflog
,
const
git_oid
*
new_oi
d
,
const
git_signature
*
committer
,
const
char
*
msg
);
/**
* Rename the reflog for the given reference
...
...
@@ -87,6 +95,26 @@ GIT_EXTERN(unsigned int) git_reflog_entrycount(git_reflog *reflog);
GIT_EXTERN
(
const
git_reflog_entry
*
)
git_reflog_entry_byindex
(
git_reflog
*
reflog
,
unsigned
int
idx
);
/**
* Remove an entry from the reflog by its index
*
* To ensure there's no gap in the log history, set the `rewrite_previosu_entry` to 1.
* When deleting entry `n`, member old_oid of entry `n-1` (if any) will be updated with
* the value of memeber new_oid of entry `n+1`.
*
* @param reflog a previously loaded reflog.
*
* @param idx the position of the entry to remove.
*
* @param rewrite_previous_entry 1 to rewrite the history; 0 otherwise.
*
* @return 0 on success or an error code.
*/
GIT_EXTERN
(
int
)
git_reflog_entry_drop
(
git_reflog
*
reflog
,
unsigned
int
idx
,
int
rewrite_previous_entry
);
/**
* Get the old oid
*
* @param entry a reflog entry
...
...
src/reflog.c
View file @
43b67d49
This diff is collapsed.
Click to expand it.
src/reflog.h
View file @
43b67d49
...
...
@@ -17,6 +17,8 @@
#define GIT_REFLOG_SIZE_MIN (2*GIT_OID_HEXSZ+2+17)
#define GIT_OID_HEX_ZERO "0000000000000000000000000000000000000000"
struct
git_reflog_entry
{
git_oid
oid_old
;
git_oid
oid_cur
;
...
...
@@ -28,6 +30,7 @@ struct git_reflog_entry {
struct
git_reflog
{
char
*
ref_name
;
git_repository
*
owner
;
git_vector
entries
;
};
...
...
tests-clar/refs/reflog/drop.c
0 → 100644
View file @
43b67d49
#include "clar_libgit2.h"
#include "reflog.h"
static
git_repository
*
g_repo
;
static
git_reflog
*
g_reflog
;
static
unsigned
int
entrycount
;
void
test_refs_reflog_drop__initialize
(
void
)
{
git_reference
*
ref
;
g_repo
=
cl_git_sandbox_init
(
"testrepo.git"
);
cl_git_pass
(
git_reference_lookup
(
&
ref
,
g_repo
,
"HEAD"
));
git_reflog_read
(
&
g_reflog
,
ref
);
entrycount
=
git_reflog_entrycount
(
g_reflog
);
git_reference_free
(
ref
);
}
void
test_refs_reflog_drop__cleanup
(
void
)
{
git_reflog_free
(
g_reflog
);
cl_git_sandbox_cleanup
();
}
void
test_refs_reflog_drop__dropping_a_non_exisiting_entry_from_the_log_returns_ENOTFOUND
(
void
)
{
cl_assert_equal_i
(
GIT_ENOTFOUND
,
git_reflog_entry_drop
(
g_reflog
,
entrycount
,
0
));
cl_assert_equal_i
(
entrycount
,
git_reflog_entrycount
(
g_reflog
));
}
void
test_refs_reflog_drop__can_drop_an_entry
(
void
)
{
cl_assert
(
entrycount
>
4
);
cl_git_pass
(
git_reflog_entry_drop
(
g_reflog
,
2
,
0
));
cl_assert_equal_i
(
entrycount
-
1
,
git_reflog_entrycount
(
g_reflog
));
}
void
test_refs_reflog_drop__can_drop_an_entry_and_rewrite_the_log_history
(
void
)
{
const
git_reflog_entry
*
before_previous
,
*
before_next
;
const
git_reflog_entry
*
after_next
;
git_oid
before_next_old_oid
;
cl_assert
(
entrycount
>
4
);
before_previous
=
git_reflog_entry_byindex
(
g_reflog
,
3
);
before_next
=
git_reflog_entry_byindex
(
g_reflog
,
1
);
git_oid_cpy
(
&
before_next_old_oid
,
&
before_next
->
oid_old
);
cl_git_pass
(
git_reflog_entry_drop
(
g_reflog
,
2
,
1
));
cl_assert_equal_i
(
entrycount
-
1
,
git_reflog_entrycount
(
g_reflog
));
after_next
=
git_reflog_entry_byindex
(
g_reflog
,
1
);
cl_assert_equal_i
(
0
,
git_oid_cmp
(
&
before_next
->
oid_cur
,
&
after_next
->
oid_cur
));
cl_assert
(
git_oid_cmp
(
&
before_next_old_oid
,
&
after_next
->
oid_old
)
!=
0
);
cl_assert_equal_i
(
0
,
git_oid_cmp
(
&
before_previous
->
oid_cur
,
&
after_next
->
oid_old
));
}
void
test_refs_reflog_drop__can_drop_the_first_entry
(
void
)
{
cl_assert
(
entrycount
>
2
);
cl_git_pass
(
git_reflog_entry_drop
(
g_reflog
,
0
,
0
));
cl_assert_equal_i
(
entrycount
-
1
,
git_reflog_entrycount
(
g_reflog
));
}
void
test_refs_reflog_drop__can_drop_the_last_entry
(
void
)
{
const
git_reflog_entry
*
entry
;
cl_assert
(
entrycount
>
2
);
cl_git_pass
(
git_reflog_entry_drop
(
g_reflog
,
entrycount
-
1
,
0
));
cl_assert_equal_i
(
entrycount
-
1
,
git_reflog_entrycount
(
g_reflog
));
entry
=
git_reflog_entry_byindex
(
g_reflog
,
entrycount
-
2
);
cl_assert
(
git_oid_streq
(
&
entry
->
oid_old
,
GIT_OID_HEX_ZERO
)
!=
0
);
}
void
test_refs_reflog_drop__can_drop_the_last_entry_and_rewrite_the_log_history
(
void
)
{
const
git_reflog_entry
*
entry
;
cl_assert
(
entrycount
>
2
);
cl_git_pass
(
git_reflog_entry_drop
(
g_reflog
,
entrycount
-
1
,
1
));
cl_assert_equal_i
(
entrycount
-
1
,
git_reflog_entrycount
(
g_reflog
));
entry
=
git_reflog_entry_byindex
(
g_reflog
,
entrycount
-
2
);
cl_assert
(
git_oid_streq
(
&
entry
->
oid_old
,
GIT_OID_HEX_ZERO
)
==
0
);
}
void
test_refs_reflog_drop__can_drop_all_the_entries
(
void
)
{
cl_assert
(
--
entrycount
>
0
);
do
{
cl_git_pass
(
git_reflog_entry_drop
(
g_reflog
,
--
entrycount
,
1
));
}
while
(
entrycount
>
0
);
cl_git_pass
(
git_reflog_entry_drop
(
g_reflog
,
0
,
1
));
cl_assert_equal_i
(
0
,
git_reflog_entrycount
(
g_reflog
));
}
void
test_refs_reflog_drop__can_persist_deletion_on_disk
(
void
)
{
git_reference
*
ref
;
cl_assert
(
entrycount
>
2
);
cl_git_pass
(
git_reference_lookup
(
&
ref
,
g_repo
,
g_reflog
->
ref_name
));
cl_git_pass
(
git_reflog_entry_drop
(
g_reflog
,
entrycount
-
1
,
1
));
cl_assert_equal_i
(
entrycount
-
1
,
git_reflog_entrycount
(
g_reflog
));
cl_git_pass
(
git_reflog_write
(
g_reflog
));
git_reflog_free
(
g_reflog
);
git_reflog_read
(
&
g_reflog
,
ref
);
git_reference_free
(
ref
);
cl_assert_equal_i
(
entrycount
-
1
,
git_reflog_entrycount
(
g_reflog
));
}
tests-clar/refs/reflog.c
→
tests-clar/refs/reflog
/reflog
.c
View file @
43b67d49
...
...
@@ -7,7 +7,7 @@
static
const
char
*
new_ref
=
"refs/heads/test-reflog"
;
static
const
char
*
current_master_tip
=
"a65fedf39aefe402d3bb6e24df4d4f5fe4547750"
;
static
const
char
*
commit_msg
=
"commit: bla bla"
;
#define commit_msg "commit: bla bla"
static
git_repository
*
g_repo
;
...
...
@@ -24,66 +24,60 @@ static void assert_signature(git_signature *expected, git_signature *actual)
// Fixture setup and teardown
void
test_refs_reflog__initialize
(
void
)
void
test_refs_reflog_
reflog_
_initialize
(
void
)
{
g_repo
=
cl_git_sandbox_init
(
"testrepo.git"
);
}
void
test_refs_reflog__cleanup
(
void
)
void
test_refs_reflog_
reflog_
_cleanup
(
void
)
{
cl_git_sandbox_cleanup
();
}
void
test_refs_reflog__write_then_read
(
void
)
void
test_refs_reflog_reflog__append_then_read
(
void
)
{
// write a reflog for a given reference and ensure it can be read back
git_repository
*
repo2
;
git_repository
*
repo2
;
git_reference
*
ref
,
*
lookedup_ref
;
git_oid
oid
;
git_signature
*
committer
;
git_reflog
*
reflog
;
git_reflog_entry
*
entry
;
char
oid_str
[
GIT_OID_HEXSZ
+
1
];
const
git_reflog_entry
*
entry
;
/* Create a new branch pointing at the HEAD */
git_oid_fromstr
(
&
oid
,
current_master_tip
);
cl_git_pass
(
git_reference_create_oid
(
&
ref
,
g_repo
,
new_ref
,
&
oid
,
0
));
git_reference_free
(
ref
);
cl_git_pass
(
git_reference_lookup
(
&
ref
,
g_repo
,
new_ref
));
cl_git_pass
(
git_signature_now
(
&
committer
,
"foo"
,
"foo@bar"
));
cl_git_pass
(
git_reflog_write
(
ref
,
NULL
,
committer
,
NULL
));
cl_git_fail
(
git_reflog_write
(
ref
,
NULL
,
committer
,
"no ancestor NULL for an existing reflog"
));
cl_git_fail
(
git_reflog_write
(
ref
,
NULL
,
committer
,
"no
\n
newline"
));
cl_git_pass
(
git_reflog_write
(
ref
,
&
oid
,
committer
,
commit_msg
));
cl_git_pass
(
git_reflog_read
(
&
reflog
,
ref
));
cl_git_fail
(
git_reflog_append
(
reflog
,
&
oid
,
committer
,
"no inner
\n
newline"
));
cl_git_pass
(
git_reflog_append
(
reflog
,
&
oid
,
committer
,
NULL
));
cl_git_pass
(
git_reflog_append
(
reflog
,
&
oid
,
committer
,
commit_msg
"
\n
"
));
cl_git_pass
(
git_reflog_write
(
reflog
));
git_reflog_free
(
reflog
);
/* Reopen a new instance of the repository */
cl_git_pass
(
git_repository_open
(
&
repo2
,
"testrepo.git"
));
/* Lookup the pre
iv
ously created branch */
/* Lookup the pre
vi
ously created branch */
cl_git_pass
(
git_reference_lookup
(
&
lookedup_ref
,
repo2
,
new_ref
));
/* Read and parse the reflog for this branch */
cl_git_pass
(
git_reflog_read
(
&
reflog
,
lookedup_ref
));
cl_assert
(
reflog
->
entries
.
length
==
2
);
cl_assert
_equal_i
(
2
,
git_reflog_entrycount
(
reflog
)
);
entry
=
(
git_reflog_entry
*
)
git_vector_get
(
&
reflog
->
entries
,
0
);
entry
=
git_reflog_entry_byindex
(
reflog
,
0
);
assert_signature
(
committer
,
entry
->
committer
);
git_oid_tostr
(
oid_str
,
GIT_OID_HEXSZ
+
1
,
&
entry
->
oid_old
);
cl_assert_equal_s
(
"0000000000000000000000000000000000000000"
,
oid_str
);
git_oid_tostr
(
oid_str
,
GIT_OID_HEXSZ
+
1
,
&
entry
->
oid_cur
);
cl_assert_equal_s
(
current_master_tip
,
oid_str
);
cl_assert
(
git_oid_streq
(
&
entry
->
oid_old
,
GIT_OID_HEX_ZERO
)
==
0
);
cl_assert
(
git_oid_cmp
(
&
oid
,
&
entry
->
oid_cur
)
==
0
);
cl_assert
(
entry
->
msg
==
NULL
);
entry
=
(
git_reflog_entry
*
)
git_vector_get
(
&
reflog
->
entries
,
1
);
entry
=
git_reflog_entry_byindex
(
reflog
,
1
);
assert_signature
(
committer
,
entry
->
committer
);
git_oid_tostr
(
oid_str
,
GIT_OID_HEXSZ
+
1
,
&
entry
->
oid_old
);
cl_assert_equal_s
(
current_master_tip
,
oid_str
);
git_oid_tostr
(
oid_str
,
GIT_OID_HEXSZ
+
1
,
&
entry
->
oid_cur
);
cl_assert_equal_s
(
current_master_tip
,
oid_str
);
cl_assert
(
git_oid_cmp
(
&
oid
,
&
entry
->
oid_old
)
==
0
);
cl_assert
(
git_oid_cmp
(
&
oid
,
&
entry
->
oid_cur
)
==
0
);
cl_assert_equal_s
(
commit_msg
,
entry
->
msg
);
git_signature_free
(
committer
);
...
...
@@ -94,35 +88,7 @@ void test_refs_reflog__write_then_read(void)
git_reference_free
(
lookedup_ref
);
}
void
test_refs_reflog__dont_write_bad
(
void
)
{
// avoid writing an obviously wrong reflog
git_reference
*
ref
;
git_oid
oid
;
git_signature
*
committer
;
/* Create a new branch pointing at the HEAD */
git_oid_fromstr
(
&
oid
,
current_master_tip
);
cl_git_pass
(
git_reference_create_oid
(
&
ref
,
g_repo
,
new_ref
,
&
oid
,
0
));
git_reference_free
(
ref
);
cl_git_pass
(
git_reference_lookup
(
&
ref
,
g_repo
,
new_ref
));
cl_git_pass
(
git_signature_now
(
&
committer
,
"foo"
,
"foo@bar"
));
/* Write the reflog for the new branch */
cl_git_pass
(
git_reflog_write
(
ref
,
NULL
,
committer
,
NULL
));
/* Try to update the reflog with wrong information:
* It's no new reference, so the ancestor OID cannot
* be NULL. */
cl_git_fail
(
git_reflog_write
(
ref
,
NULL
,
committer
,
NULL
));
git_signature_free
(
committer
);
git_reference_free
(
ref
);
}
void
test_refs_reflog__renaming_the_reference_moves_the_reflog
(
void
)
void
test_refs_reflog_reflog__renaming_the_reference_moves_the_reflog
(
void
)
{
git_reference
*
master
;
git_buf
master_log_path
=
GIT_BUF_INIT
,
moved_log_path
=
GIT_BUF_INIT
;
...
...
@@ -145,6 +111,7 @@ void test_refs_reflog__renaming_the_reference_moves_the_reflog(void)
git_buf_free
(
&
moved_log_path
);
git_buf_free
(
&
master_log_path
);
}
static
void
assert_has_reflog
(
bool
expected_result
,
const
char
*
name
)
{
git_reference
*
ref
;
...
...
@@ -156,9 +123,50 @@ static void assert_has_reflog(bool expected_result, const char *name)
git_reference_free
(
ref
);
}
void
test_refs_reflog__reference_has_reflog
(
void
)
void
test_refs_reflog_
reflog_
_reference_has_reflog
(
void
)
{
assert_has_reflog
(
true
,
"HEAD"
);
assert_has_reflog
(
true
,
"refs/heads/master"
);
assert_has_reflog
(
false
,
"refs/heads/subtrees"
);
}
void
test_refs_reflog_reflog__reading_the_reflog_from_a_reference_with_no_log_returns_an_empty_one
(
void
)
{
git_reference
*
subtrees
;
git_reflog
*
reflog
;
git_buf
subtrees_log_path
=
GIT_BUF_INIT
;
cl_git_pass
(
git_reference_lookup
(
&
subtrees
,
g_repo
,
"refs/heads/subtrees"
));
git_buf_join_n
(
&
subtrees_log_path
,
'/'
,
3
,
git_repository_path
(
g_repo
),
GIT_REFLOG_DIR
,
git_reference_name
(
subtrees
));
cl_assert_equal_i
(
false
,
git_path_isfile
(
git_buf_cstr
(
&
subtrees_log_path
)));
cl_git_pass
(
git_reflog_read
(
&
reflog
,
subtrees
));
cl_assert_equal_i
(
0
,
git_reflog_entrycount
(
reflog
));
git_reflog_free
(
reflog
);
git_reference_free
(
subtrees
);
git_buf_free
(
&
subtrees_log_path
);
}
void
test_refs_reflog_reflog__cannot_write_a_moved_reflog
(
void
)
{
git_reference
*
master
;
git_buf
master_log_path
=
GIT_BUF_INIT
,
moved_log_path
=
GIT_BUF_INIT
;
git_reflog
*
reflog
;
cl_git_pass
(
git_reference_lookup
(
&
master
,
g_repo
,
"refs/heads/master"
));
cl_git_pass
(
git_reflog_read
(
&
reflog
,
master
));
cl_git_pass
(
git_reflog_write
(
reflog
));
cl_git_pass
(
git_reference_rename
(
master
,
"refs/moved"
,
0
));
cl_git_fail
(
git_reflog_write
(
reflog
));
git_reflog_free
(
reflog
);
git_reference_free
(
master
);
git_buf_free
(
&
moved_log_path
);
git_buf_free
(
&
master_log_path
);
}
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