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
8f4a8b09
Commit
8f4a8b09
authored
Oct 28, 2013
by
Ben Straub
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #1802 from libgit2/cmn/reflog-backend
Make reflog part of refdb
parents
a1efa596
0174794a
Hide whitespace changes
Inline
Side-by-side
Showing
14 changed files
with
571 additions
and
397 deletions
+571
-397
include/git2/reflog.h
+28
-8
include/git2/sys/refdb_backend.h
+20
-0
include/git2/sys/reflog.h
+21
-0
src/refdb.c
+16
-0
src/refdb.h
+4
-0
src/refdb_fs.c
+345
-0
src/reflog.c
+55
-327
src/reflog.h
+6
-1
src/refs.c
+1
-1
src/revparse.c
+2
-2
src/stash.c
+6
-5
tests-clar/refs/reflog/drop.c
+2
-11
tests-clar/refs/reflog/reflog.c
+63
-40
tests-clar/stash/drop.c
+2
-2
No files found.
include/git2/reflog.h
View file @
8f4a8b09
...
...
@@ -31,10 +31,11 @@ GIT_BEGIN_DECL
* git_reflog_free().
*
* @param out pointer to reflog
* @param ref reference to read the reflog for
* @param repo the repostiory
* @param name reference to look up
* @return 0 or an error code
*/
GIT_EXTERN
(
int
)
git_reflog_read
(
git_reflog
**
out
,
const
git_reference
*
ref
);
GIT_EXTERN
(
int
)
git_reflog_read
(
git_reflog
**
out
,
git_repository
*
repo
,
const
char
*
name
);
/**
* Write an existing in-memory reflog object back to disk
...
...
@@ -59,26 +60,45 @@ GIT_EXTERN(int) git_reflog_write(git_reflog *reflog);
GIT_EXTERN
(
int
)
git_reflog_append
(
git_reflog
*
reflog
,
const
git_oid
*
id
,
const
git_signature
*
committer
,
const
char
*
msg
);
/**
* Rename the reflog for the given reference
* Add a new entry to the named reflog.
*
* This utility function loads the named reflog, appends to it and
* writes it back out to the backend.
*
* `msg` is optional and can be NULL.
*
* @param repo the repository to act on
* @param name the reflog's name
* @param id 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_append_to
(
git_repository
*
repo
,
const
char
*
name
,
const
git_oid
*
id
,
const
git_signature
*
committer
,
const
char
*
msg
);
/**
* Rename a reflog
*
* The reflog to be renamed is expected to already exist
*
* The new name will be checked for validity.
* See `git_reference_create_symbolic()` for rules about valid names.
*
* @param ref the reference
* @param name the new name of the reference
* @param repo the repository
* @param old_name the old name of the reference
* @param new_name the new name of the reference
* @return 0 on success, GIT_EINVALIDSPEC or an error code
*/
GIT_EXTERN
(
int
)
git_reflog_rename
(
git_re
ference
*
ref
,
const
char
*
name
);
GIT_EXTERN
(
int
)
git_reflog_rename
(
git_re
pository
*
repo
,
const
char
*
old_name
,
const
char
*
name
);
/**
* Delete the reflog for the given reference
*
* @param ref the reference
* @param repo the repository
* @param name the reflog to delete
* @return 0 or an error code
*/
GIT_EXTERN
(
int
)
git_reflog_delete
(
git_re
ference
*
ref
);
GIT_EXTERN
(
int
)
git_reflog_delete
(
git_re
pository
*
repo
,
const
char
*
name
);
/**
* Get the number of log entries in a reflog
...
...
include/git2/sys/refdb_backend.h
View file @
8f4a8b09
...
...
@@ -119,6 +119,26 @@ struct git_refdb_backend {
* provide this function; if it is not provided, nothing will be done.
*/
void
(
*
free
)(
git_refdb_backend
*
backend
);
/**
* Read the reflog for the given reference name.
*/
int
(
*
reflog_read
)(
git_reflog
**
out
,
git_refdb_backend
*
backend
,
const
char
*
name
);
/**
* Write a reflog to disk.
*/
int
(
*
reflog_write
)(
git_refdb_backend
*
backend
,
git_reflog
*
reflog
);
/**
* Rename a reflog
*/
int
(
*
reflog_rename
)(
git_refdb_backend
*
_backend
,
const
char
*
old_name
,
const
char
*
new_name
);
/**
* Remove a reflog.
*/
int
(
*
reflog_delete
)(
git_refdb_backend
*
backend
,
const
char
*
name
);
};
#define GIT_REFDB_BACKEND_VERSION 1
...
...
include/git2/sys/reflog.h
0 → 100644
View file @
8f4a8b09
/*
* 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_sys_git_reflog_h__
#define INCLUDE_sys_git_reflog_h__
#include "git2/common.h"
#include "git2/types.h"
#include "git2/oid.h"
GIT_BEGIN_DECL
GIT_EXTERN
(
git_reflog_entry
*
)
git_reflog_entry__alloc
(
void
);
GIT_EXTERN
(
void
)
git_reflog_entry__free
(
git_reflog_entry
*
entry
);
GIT_END_DECL
#endif
src/refdb.c
View file @
8f4a8b09
...
...
@@ -16,6 +16,7 @@
#include "hash.h"
#include "refdb.h"
#include "refs.h"
#include "reflog.h"
int
git_refdb_new
(
git_refdb
**
out
,
git_repository
*
repo
)
{
...
...
@@ -203,3 +204,18 @@ int git_refdb_delete(struct git_refdb *db, const char *ref_name)
assert
(
db
&&
db
->
backend
);
return
db
->
backend
->
del
(
db
->
backend
,
ref_name
);
}
int
git_refdb_reflog_read
(
git_reflog
**
out
,
git_refdb
*
db
,
const
char
*
name
)
{
int
error
;
assert
(
db
&&
db
->
backend
);
if
((
error
=
db
->
backend
->
reflog_read
(
out
,
db
->
backend
,
name
))
<
0
)
return
error
;
GIT_REFCOUNT_INC
(
db
);
(
*
out
)
->
db
=
db
;
return
0
;
}
src/refdb.h
View file @
8f4a8b09
...
...
@@ -43,4 +43,8 @@ void git_refdb_iterator_free(git_reference_iterator *iter);
int
git_refdb_write
(
git_refdb
*
refdb
,
git_reference
*
ref
,
int
force
);
int
git_refdb_delete
(
git_refdb
*
refdb
,
const
char
*
ref_name
);
int
git_refdb_reflog_read
(
git_reflog
**
out
,
git_refdb
*
db
,
const
char
*
name
);
int
git_refdb_reflog_write
(
git_reflog
*
reflog
);
#endif
src/refdb_fs.c
View file @
8f4a8b09
...
...
@@ -16,12 +16,14 @@
#include "refdb_fs.h"
#include "iterator.h"
#include "sortedcache.h"
#include "signature.h"
#include <git2/tag.h>
#include <git2/object.h>
#include <git2/refdb.h>
#include <git2/sys/refdb_backend.h>
#include <git2/sys/refs.h>
#include <git2/sys/reflog.h>
GIT__USE_STRMAP
;
...
...
@@ -1071,6 +1073,345 @@ static int setup_namespace(git_buf *path, git_repository *repo)
return
0
;
}
static
int
reflog_alloc
(
git_reflog
**
reflog
,
const
char
*
name
)
{
git_reflog
*
log
;
*
reflog
=
NULL
;
log
=
git__calloc
(
1
,
sizeof
(
git_reflog
));
GITERR_CHECK_ALLOC
(
log
);
log
->
ref_name
=
git__strdup
(
name
);
GITERR_CHECK_ALLOC
(
log
->
ref_name
);
if
(
git_vector_init
(
&
log
->
entries
,
0
,
NULL
)
<
0
)
{
git__free
(
log
->
ref_name
);
git__free
(
log
);
return
-
1
;
}
*
reflog
=
log
;
return
0
;
}
static
int
reflog_parse
(
git_reflog
*
log
,
const
char
*
buf
,
size_t
buf_size
)
{
const
char
*
ptr
;
git_reflog_entry
*
entry
;
#define seek_forward(_increase) do { \
if (_increase >= buf_size) { \
giterr_set(GITERR_INVALID, "Ran out of data while parsing reflog"); \
goto fail; \
} \
buf += _increase; \
buf_size -= _increase; \
} while (0)
while
(
buf_size
>
GIT_REFLOG_SIZE_MIN
)
{
entry
=
git__calloc
(
1
,
sizeof
(
git_reflog_entry
));
GITERR_CHECK_ALLOC
(
entry
);
entry
->
committer
=
git__malloc
(
sizeof
(
git_signature
));
GITERR_CHECK_ALLOC
(
entry
->
committer
);
if
(
git_oid_fromstrn
(
&
entry
->
oid_old
,
buf
,
GIT_OID_HEXSZ
)
<
0
)
goto
fail
;
seek_forward
(
GIT_OID_HEXSZ
+
1
);
if
(
git_oid_fromstrn
(
&
entry
->
oid_cur
,
buf
,
GIT_OID_HEXSZ
)
<
0
)
goto
fail
;
seek_forward
(
GIT_OID_HEXSZ
+
1
);
ptr
=
buf
;
/* Seek forward to the end of the signature. */
while
(
*
buf
&&
*
buf
!=
'\t'
&&
*
buf
!=
'\n'
)
seek_forward
(
1
);
if
(
git_signature__parse
(
entry
->
committer
,
&
ptr
,
buf
+
1
,
NULL
,
*
buf
)
<
0
)
goto
fail
;
if
(
*
buf
==
'\t'
)
{
/* We got a message. Read everything till we reach LF. */
seek_forward
(
1
);
ptr
=
buf
;
while
(
*
buf
&&
*
buf
!=
'\n'
)
seek_forward
(
1
);
entry
->
msg
=
git__strndup
(
ptr
,
buf
-
ptr
);
GITERR_CHECK_ALLOC
(
entry
->
msg
);
}
else
entry
->
msg
=
NULL
;
while
(
*
buf
&&
*
buf
==
'\n'
&&
buf_size
>
1
)
seek_forward
(
1
);
if
(
git_vector_insert
(
&
log
->
entries
,
entry
)
<
0
)
goto
fail
;
}
return
0
;
#undef seek_forward
fail:
if
(
entry
)
git_reflog_entry__free
(
entry
);
return
-
1
;
}
static
int
create_new_reflog_file
(
const
char
*
filepath
)
{
int
fd
,
error
;
if
((
error
=
git_futils_mkpath2file
(
filepath
,
GIT_REFLOG_DIR_MODE
))
<
0
)
return
error
;
if
((
fd
=
p_open
(
filepath
,
O_WRONLY
|
O_CREAT
|
O_TRUNC
,
GIT_REFLOG_FILE_MODE
))
<
0
)
return
-
1
;
return
p_close
(
fd
);
}
GIT_INLINE
(
int
)
retrieve_reflog_path
(
git_buf
*
path
,
git_repository
*
repo
,
const
char
*
name
)
{
return
git_buf_join_n
(
path
,
'/'
,
3
,
repo
->
path_repository
,
GIT_REFLOG_DIR
,
name
);
}
static
int
refdb_reflog_fs__read
(
git_reflog
**
out
,
git_refdb_backend
*
_backend
,
const
char
*
name
)
{
int
error
=
-
1
;
git_buf
log_path
=
GIT_BUF_INIT
;
git_buf
log_file
=
GIT_BUF_INIT
;
git_reflog
*
log
=
NULL
;
git_repository
*
repo
;
refdb_fs_backend
*
backend
;
assert
(
out
&&
_backend
&&
name
);
backend
=
(
refdb_fs_backend
*
)
_backend
;
repo
=
backend
->
repo
;
if
(
reflog_alloc
(
&
log
,
name
)
<
0
)
return
-
1
;
if
(
retrieve_reflog_path
(
&
log_path
,
repo
,
name
)
<
0
)
goto
cleanup
;
error
=
git_futils_readbuffer
(
&
log_file
,
git_buf_cstr
(
&
log_path
));
if
(
error
<
0
&&
error
!=
GIT_ENOTFOUND
)
goto
cleanup
;
if
((
error
==
GIT_ENOTFOUND
)
&&
((
error
=
create_new_reflog_file
(
git_buf_cstr
(
&
log_path
)))
<
0
))
goto
cleanup
;
if
((
error
=
reflog_parse
(
log
,
git_buf_cstr
(
&
log_file
),
git_buf_len
(
&
log_file
)))
<
0
)
goto
cleanup
;
*
out
=
log
;
goto
success
;
cleanup
:
git_reflog_free
(
log
);
success
:
git_buf_free
(
&
log_file
);
git_buf_free
(
&
log_path
);
return
error
;
}
static
int
serialize_reflog_entry
(
git_buf
*
buf
,
const
git_oid
*
oid_old
,
const
git_oid
*
oid_new
,
const
git_signature
*
committer
,
const
char
*
msg
)
{
char
raw_old
[
GIT_OID_HEXSZ
+
1
];
char
raw_new
[
GIT_OID_HEXSZ
+
1
];
git_oid_tostr
(
raw_old
,
GIT_OID_HEXSZ
+
1
,
oid_old
);
git_oid_tostr
(
raw_new
,
GIT_OID_HEXSZ
+
1
,
oid_new
);
git_buf_clear
(
buf
);
git_buf_puts
(
buf
,
raw_old
);
git_buf_putc
(
buf
,
' '
);
git_buf_puts
(
buf
,
raw_new
);
git_signature__writebuf
(
buf
,
" "
,
committer
);
/* drop trailing LF */
git_buf_rtrim
(
buf
);
if
(
msg
)
{
git_buf_putc
(
buf
,
'\t'
);
git_buf_puts
(
buf
,
msg
);
}
git_buf_putc
(
buf
,
'\n'
);
return
git_buf_oom
(
buf
);
}
static
int
refdb_reflog_fs__write
(
git_refdb_backend
*
_backend
,
git_reflog
*
reflog
)
{
int
error
=
-
1
;
unsigned
int
i
;
git_reflog_entry
*
entry
;
git_repository
*
repo
;
refdb_fs_backend
*
backend
;
git_buf
log_path
=
GIT_BUF_INIT
;
git_buf
log
=
GIT_BUF_INIT
;
git_filebuf
fbuf
=
GIT_FILEBUF_INIT
;
assert
(
_backend
&&
reflog
);
backend
=
(
refdb_fs_backend
*
)
_backend
;
repo
=
backend
->
repo
;
if
(
retrieve_reflog_path
(
&
log_path
,
repo
,
reflog
->
ref_name
)
<
0
)
return
-
1
;
if
(
!
git_path_isfile
(
git_buf_cstr
(
&
log_path
)))
{
giterr_set
(
GITERR_INVALID
,
"Log file for reference '%s' doesn't exist."
,
reflog
->
ref_name
);
goto
cleanup
;
}
if
((
error
=
git_filebuf_open
(
&
fbuf
,
git_buf_cstr
(
&
log_path
),
0
))
<
0
)
goto
cleanup
;
git_vector_foreach
(
&
reflog
->
entries
,
i
,
entry
)
{
if
(
serialize_reflog_entry
(
&
log
,
&
(
entry
->
oid_old
),
&
(
entry
->
oid_cur
),
entry
->
committer
,
entry
->
msg
)
<
0
)
goto
cleanup
;
if
((
error
=
git_filebuf_write
(
&
fbuf
,
log
.
ptr
,
log
.
size
))
<
0
)
goto
cleanup
;
}
error
=
git_filebuf_commit
(
&
fbuf
,
GIT_REFLOG_FILE_MODE
);
goto
success
;
cleanup
:
git_filebuf_cleanup
(
&
fbuf
);
success
:
git_buf_free
(
&
log
);
git_buf_free
(
&
log_path
);
return
error
;
}
static
int
refdb_reflog_fs__rename
(
git_refdb_backend
*
_backend
,
const
char
*
old_name
,
const
char
*
new_name
)
{
int
error
=
0
,
fd
;
git_buf
old_path
=
GIT_BUF_INIT
;
git_buf
new_path
=
GIT_BUF_INIT
;
git_buf
temp_path
=
GIT_BUF_INIT
;
git_buf
normalized
=
GIT_BUF_INIT
;
git_repository
*
repo
;
refdb_fs_backend
*
backend
;
assert
(
_backend
&&
old_name
&&
new_name
);
backend
=
(
refdb_fs_backend
*
)
_backend
;
repo
=
backend
->
repo
;
if
((
error
=
git_reference__normalize_name
(
&
normalized
,
new_name
,
GIT_REF_FORMAT_ALLOW_ONELEVEL
))
<
0
)
return
error
;
if
(
git_buf_joinpath
(
&
temp_path
,
repo
->
path_repository
,
GIT_REFLOG_DIR
)
<
0
)
return
-
1
;
if
(
git_buf_joinpath
(
&
old_path
,
git_buf_cstr
(
&
temp_path
),
old_name
)
<
0
)
return
-
1
;
if
(
git_buf_joinpath
(
&
new_path
,
git_buf_cstr
(
&
temp_path
),
git_buf_cstr
(
&
normalized
))
<
0
)
return
-
1
;
/*
* Move the reflog to a temporary place. This two-phase renaming is required
* in order to cope with funny renaming use cases when one tries to move a reference
* to a partially colliding namespace:
* - a/b -> a/b/c
* - a/b/c/d -> a/b/c
*/
if
(
git_buf_joinpath
(
&
temp_path
,
git_buf_cstr
(
&
temp_path
),
"temp_reflog"
)
<
0
)
return
-
1
;
if
((
fd
=
git_futils_mktmp
(
&
temp_path
,
git_buf_cstr
(
&
temp_path
)))
<
0
)
{
error
=
-
1
;
goto
cleanup
;
}
p_close
(
fd
);
if
(
p_rename
(
git_buf_cstr
(
&
old_path
),
git_buf_cstr
(
&
temp_path
))
<
0
)
{
giterr_set
(
GITERR_OS
,
"Failed to rename reflog for %s"
,
new_name
);
error
=
-
1
;
goto
cleanup
;
}
if
(
git_path_isdir
(
git_buf_cstr
(
&
new_path
))
&&
(
git_futils_rmdir_r
(
git_buf_cstr
(
&
new_path
),
NULL
,
GIT_RMDIR_SKIP_NONEMPTY
)
<
0
))
{
error
=
-
1
;
goto
cleanup
;
}
if
(
git_futils_mkpath2file
(
git_buf_cstr
(
&
new_path
),
GIT_REFLOG_DIR_MODE
)
<
0
)
{
error
=
-
1
;
goto
cleanup
;
}
if
(
p_rename
(
git_buf_cstr
(
&
temp_path
),
git_buf_cstr
(
&
new_path
))
<
0
)
{
giterr_set
(
GITERR_OS
,
"Failed to rename reflog for %s"
,
new_name
);
error
=
-
1
;
}
cleanup
:
git_buf_free
(
&
temp_path
);
git_buf_free
(
&
old_path
);
git_buf_free
(
&
new_path
);
git_buf_free
(
&
normalized
);
return
error
;
}
static
int
refdb_reflog_fs__delete
(
git_refdb_backend
*
_backend
,
const
char
*
name
)
{
int
error
;
git_buf
path
=
GIT_BUF_INIT
;
git_repository
*
repo
;
refdb_fs_backend
*
backend
;
assert
(
_backend
&&
name
);
backend
=
(
refdb_fs_backend
*
)
_backend
;
repo
=
backend
->
repo
;
error
=
retrieve_reflog_path
(
&
path
,
repo
,
name
);
if
(
!
error
&&
git_path_exists
(
path
.
ptr
))
error
=
p_unlink
(
path
.
ptr
);
git_buf_free
(
&
path
);
return
error
;
}
int
git_refdb_backend_fs
(
git_refdb_backend
**
backend_out
,
git_repository
*
repository
)
...
...
@@ -1114,6 +1455,10 @@ int git_refdb_backend_fs(
backend
->
parent
.
rename
=
&
refdb_fs_backend__rename
;
backend
->
parent
.
compress
=
&
refdb_fs_backend__compress
;
backend
->
parent
.
free
=
&
refdb_fs_backend__free
;
backend
->
parent
.
reflog_read
=
&
refdb_reflog_fs__read
;
backend
->
parent
.
reflog_write
=
&
refdb_reflog_fs__write
;
backend
->
parent
.
reflog_rename
=
&
refdb_reflog_fs__rename
;
backend
->
parent
.
reflog_delete
=
&
refdb_reflog_fs__delete
;
*
backend_out
=
(
git_refdb_backend
*
)
backend
;
return
0
;
...
...
src/reflog.c
View file @
8f4a8b09
...
...
@@ -9,82 +9,16 @@
#include "repository.h"
#include "filebuf.h"
#include "signature.h"
#include "refdb.h"
static
int
reflog_init
(
git_reflog
**
reflog
,
const
git_reference
*
ref
)
{
git_reflog
*
log
;
*
reflog
=
NULL
;
log
=
git__calloc
(
1
,
sizeof
(
git_reflog
));
GITERR_CHECK_ALLOC
(
log
);
log
->
ref_name
=
git__strdup
(
ref
->
name
);
GITERR_CHECK_ALLOC
(
log
->
ref_name
);
if
(
git_vector_init
(
&
log
->
entries
,
0
,
NULL
)
<
0
)
{
git__free
(
log
->
ref_name
);
git__free
(
log
);
return
-
1
;
}
log
->
owner
=
git_reference_owner
(
ref
);
*
reflog
=
log
;
#include <git2/sys/refdb_backend.h>
return
0
;
}
static
int
serialize_reflog_entry
(
git_buf
*
buf
,
const
git_oid
*
oid_old
,
const
git_oid
*
oid_new
,
const
git_signature
*
committer
,
const
char
*
msg
)
git_reflog_entry
*
git_reflog_entry__alloc
(
void
)
{
char
raw_old
[
GIT_OID_HEXSZ
+
1
];
char
raw_new
[
GIT_OID_HEXSZ
+
1
];
git_oid_tostr
(
raw_old
,
GIT_OID_HEXSZ
+
1
,
oid_old
);
git_oid_tostr
(
raw_new
,
GIT_OID_HEXSZ
+
1
,
oid_new
);
git_buf_clear
(
buf
);
git_buf_puts
(
buf
,
raw_old
);
git_buf_putc
(
buf
,
' '
);
git_buf_puts
(
buf
,
raw_new
);
git_signature__writebuf
(
buf
,
" "
,
committer
);
/* drop trailing LF */
git_buf_rtrim
(
buf
);
if
(
msg
)
{
git_buf_putc
(
buf
,
'\t'
);
git_buf_puts
(
buf
,
msg
);
}
git_buf_putc
(
buf
,
'\n'
);
return
git_buf_oom
(
buf
);
}
static
int
reflog_entry_new
(
git_reflog_entry
**
entry
)
{
git_reflog_entry
*
e
;
assert
(
entry
);
e
=
git__malloc
(
sizeof
(
git_reflog_entry
));
GITERR_CHECK_ALLOC
(
e
);
memset
(
e
,
0
,
sizeof
(
git_reflog_entry
));
*
entry
=
e
;
return
0
;
return
git__calloc
(
1
,
sizeof
(
git_reflog_entry
));
}
static
void
reflog_entry
_free
(
git_reflog_entry
*
entry
)
void
git_reflog_entry_
_free
(
git_reflog_entry
*
entry
)
{
git_signature_free
(
entry
->
committer
);
...
...
@@ -92,75 +26,6 @@ static void reflog_entry_free(git_reflog_entry *entry)
git__free
(
entry
);
}
static
int
reflog_parse
(
git_reflog
*
log
,
const
char
*
buf
,
size_t
buf_size
)
{
const
char
*
ptr
;
git_reflog_entry
*
entry
;
#define seek_forward(_increase) do { \
if (_increase >= buf_size) { \
giterr_set(GITERR_INVALID, "Ran out of data while parsing reflog"); \
goto fail; \
} \
buf += _increase; \
buf_size -= _increase; \
} while (0)
while
(
buf_size
>
GIT_REFLOG_SIZE_MIN
)
{
if
(
reflog_entry_new
(
&
entry
)
<
0
)
return
-
1
;
entry
->
committer
=
git__malloc
(
sizeof
(
git_signature
));
GITERR_CHECK_ALLOC
(
entry
->
committer
);
if
(
git_oid_fromstrn
(
&
entry
->
oid_old
,
buf
,
GIT_OID_HEXSZ
)
<
0
)
goto
fail
;
seek_forward
(
GIT_OID_HEXSZ
+
1
);
if
(
git_oid_fromstrn
(
&
entry
->
oid_cur
,
buf
,
GIT_OID_HEXSZ
)
<
0
)
goto
fail
;
seek_forward
(
GIT_OID_HEXSZ
+
1
);
ptr
=
buf
;
/* Seek forward to the end of the signature. */
while
(
*
buf
&&
*
buf
!=
'\t'
&&
*
buf
!=
'\n'
)
seek_forward
(
1
);
if
(
git_signature__parse
(
entry
->
committer
,
&
ptr
,
buf
+
1
,
NULL
,
*
buf
)
<
0
)
goto
fail
;
if
(
*
buf
==
'\t'
)
{
/* We got a message. Read everything till we reach LF. */
seek_forward
(
1
);
ptr
=
buf
;
while
(
*
buf
&&
*
buf
!=
'\n'
)
seek_forward
(
1
);
entry
->
msg
=
git__strndup
(
ptr
,
buf
-
ptr
);
GITERR_CHECK_ALLOC
(
entry
->
msg
);
}
else
entry
->
msg
=
NULL
;
while
(
*
buf
&&
*
buf
==
'\n'
&&
buf_size
>
1
)
seek_forward
(
1
);
if
(
git_vector_insert
(
&
log
->
entries
,
entry
)
<
0
)
goto
fail
;
}
return
0
;
#undef seek_forward
fail:
if
(
entry
)
reflog_entry_free
(
entry
);
return
-
1
;
}
void
git_reflog_free
(
git_reflog
*
reflog
)
{
size_t
i
;
...
...
@@ -169,10 +34,13 @@ void git_reflog_free(git_reflog *reflog)
if
(
reflog
==
NULL
)
return
;
if
(
reflog
->
db
)
GIT_REFCOUNT_DEC
(
reflog
->
db
,
git_refdb__free
);
for
(
i
=
0
;
i
<
reflog
->
entries
.
length
;
i
++
)
{
entry
=
git_vector_get
(
&
reflog
->
entries
,
i
);
reflog_entry
_free
(
entry
);
git_reflog_entry_
_free
(
entry
);
}
git_vector_free
(
&
reflog
->
entries
);
...
...
@@ -180,115 +48,30 @@ void git_reflog_free(git_reflog *reflog)
git__free
(
reflog
);
}
static
int
retrieve_reflog_path
(
git_buf
*
path
,
const
git_reference
*
ref
)
int
git_reflog_read
(
git_reflog
**
reflog
,
git_repository
*
repo
,
const
char
*
name
)
{
return
git_buf_join_n
(
path
,
'/'
,
3
,
git_reference_owner
(
ref
)
->
path_repository
,
GIT_REFLOG_DIR
,
ref
->
name
);
}
git_refdb
*
refdb
;
int
error
;
static
int
create_new_reflog_file
(
const
char
*
filepath
)
{
int
fd
,
error
;
assert
(
reflog
&&
repo
&&
name
);
if
((
error
=
git_
futils_mkpath2file
(
filepath
,
GIT_REFLOG_DIR_MODE
))
<
0
)
if
((
error
=
git_
repository_refdb__weakptr
(
&
refdb
,
repo
))
<
0
)
return
error
;
if
((
fd
=
p_open
(
filepath
,
O_WRONLY
|
O_CREAT
|
O_TRUNC
,
GIT_REFLOG_FILE_MODE
))
<
0
)
return
-
1
;
return
p_close
(
fd
);
}
int
git_reflog_read
(
git_reflog
**
reflog
,
const
git_reference
*
ref
)
{
int
error
=
-
1
;
git_buf
log_path
=
GIT_BUF_INIT
;
git_buf
log_file
=
GIT_BUF_INIT
;
git_reflog
*
log
=
NULL
;
assert
(
reflog
&&
ref
);
*
reflog
=
NULL
;
if
(
reflog_init
(
&
log
,
ref
)
<
0
)
return
-
1
;
if
(
retrieve_reflog_path
(
&
log_path
,
ref
)
<
0
)
goto
cleanup
;
error
=
git_futils_readbuffer
(
&
log_file
,
git_buf_cstr
(
&
log_path
));
if
(
error
<
0
&&
error
!=
GIT_ENOTFOUND
)
goto
cleanup
;
if
((
error
==
GIT_ENOTFOUND
)
&&
((
error
=
create_new_reflog_file
(
git_buf_cstr
(
&
log_path
)))
<
0
))
goto
cleanup
;
if
((
error
=
reflog_parse
(
log
,
git_buf_cstr
(
&
log_file
),
git_buf_len
(
&
log_file
)))
<
0
)
goto
cleanup
;
*
reflog
=
log
;
goto
success
;
cleanup:
git_reflog_free
(
log
);
success:
git_buf_free
(
&
log_file
);
git_buf_free
(
&
log_path
);
return
error
;
return
git_refdb_reflog_read
(
reflog
,
refdb
,
name
);
}
int
git_reflog_write
(
git_reflog
*
reflog
)
{
int
error
=
-
1
;
unsigned
int
i
;
git_reflog_entry
*
entry
;
git_buf
log_path
=
GIT_BUF_INIT
;
git_buf
log
=
GIT_BUF_INIT
;
git_filebuf
fbuf
=
GIT_FILEBUF_INIT
;
git_refdb
*
db
;
assert
(
reflog
);
assert
(
reflog
&&
reflog
->
db
);
if
(
git_buf_join_n
(
&
log_path
,
'/'
,
3
,
git_repository_path
(
reflog
->
owner
),
GIT_REFLOG_DIR
,
reflog
->
ref_name
)
<
0
)
return
-
1
;
if
(
!
git_path_isfile
(
git_buf_cstr
(
&
log_path
)))
{
giterr_set
(
GITERR_INVALID
,
"Log file for reference '%s' doesn't exist."
,
reflog
->
ref_name
);
goto
cleanup
;
}
if
((
error
=
git_filebuf_open
(
&
fbuf
,
git_buf_cstr
(
&
log_path
),
0
))
<
0
)
goto
cleanup
;
git_vector_foreach
(
&
reflog
->
entries
,
i
,
entry
)
{
if
(
serialize_reflog_entry
(
&
log
,
&
(
entry
->
oid_old
),
&
(
entry
->
oid_cur
),
entry
->
committer
,
entry
->
msg
)
<
0
)
goto
cleanup
;
if
((
error
=
git_filebuf_write
(
&
fbuf
,
log
.
ptr
,
log
.
size
))
<
0
)
goto
cleanup
;
}
error
=
git_filebuf_commit
(
&
fbuf
,
GIT_REFLOG_FILE_MODE
);
goto
success
;
cleanup:
git_filebuf_cleanup
(
&
fbuf
);
success:
git_buf_free
(
&
log
);
git_buf_free
(
&
log_path
);
return
error
;
db
=
reflog
->
db
;
return
db
->
backend
->
reflog_write
(
db
->
backend
,
reflog
);
}
int
git_reflog_append
(
git_reflog
*
reflog
,
const
git_oid
*
new_oid
,
const
git_signature
*
committer
,
const
char
*
msg
)
int
git_reflog_append
(
git_reflog
*
reflog
,
const
git_oid
*
new_oid
,
const
git_signature
*
committer
,
const
char
*
msg
)
{
git_reflog_entry
*
entry
;
const
git_reflog_entry
*
previous
;
...
...
@@ -296,8 +79,8 @@ int git_reflog_append(git_reflog *reflog, const git_oid *new_oid,
assert
(
reflog
&&
new_oid
&&
committer
);
if
(
reflog_entry_new
(
&
entry
)
<
0
)
return
-
1
;
entry
=
git__calloc
(
1
,
sizeof
(
git_reflog_entry
));
GITERR_CHECK_ALLOC
(
entry
)
;
if
((
entry
->
committer
=
git_signature_dup
(
committer
))
==
NULL
)
goto
cleanup
;
...
...
@@ -333,94 +116,30 @@ int git_reflog_append(git_reflog *reflog, const git_oid *new_oid,
return
0
;
cleanup:
reflog_entry
_free
(
entry
);
git_reflog_entry_
_free
(
entry
);
return
-
1
;
}
int
git_reflog_rename
(
git_re
ference
*
ref
,
const
char
*
new_name
)
int
git_reflog_rename
(
git_re
pository
*
repo
,
const
char
*
old_name
,
const
char
*
new_name
)
{
int
error
=
0
,
fd
;
git_buf
old_path
=
GIT_BUF_INIT
;
git_buf
new_path
=
GIT_BUF_INIT
;
git_buf
temp_path
=
GIT_BUF_INIT
;
git_buf
normalized
=
GIT_BUF_INIT
;
assert
(
ref
&&
new_name
);
if
((
error
=
git_reference__normalize_name
(
&
normalized
,
new_name
,
GIT_REF_FORMAT_ALLOW_ONELEVEL
))
<
0
)
return
error
;
if
(
git_buf_joinpath
(
&
temp_path
,
git_reference_owner
(
ref
)
->
path_repository
,
GIT_REFLOG_DIR
)
<
0
)
return
-
1
;
if
(
git_buf_joinpath
(
&
old_path
,
git_buf_cstr
(
&
temp_path
),
ref
->
name
)
<
0
)
return
-
1
;
if
(
git_buf_joinpath
(
&
new_path
,
git_buf_cstr
(
&
temp_path
),
git_buf_cstr
(
&
normalized
))
<
0
)
return
-
1
;
git_refdb
*
refdb
;
int
error
;
/*
* Move the reflog to a temporary place. This two-phase renaming is required
* in order to cope with funny renaming use cases when one tries to move a reference
* to a partially colliding namespace:
* - a/b -> a/b/c
* - a/b/c/d -> a/b/c
*/
if
(
git_buf_joinpath
(
&
temp_path
,
git_buf_cstr
(
&
temp_path
),
"temp_reflog"
)
<
0
)
if
((
error
=
git_repository_refdb__weakptr
(
&
refdb
,
repo
))
<
0
)
return
-
1
;
if
((
fd
=
git_futils_mktmp
(
&
temp_path
,
git_buf_cstr
(
&
temp_path
)))
<
0
)
{
error
=
-
1
;
goto
cleanup
;
}
p_close
(
fd
);
if
(
p_rename
(
git_buf_cstr
(
&
old_path
),
git_buf_cstr
(
&
temp_path
))
<
0
)
{
giterr_set
(
GITERR_OS
,
"Failed to rename reflog for %s"
,
new_name
);
error
=
-
1
;
goto
cleanup
;
}
if
(
git_path_isdir
(
git_buf_cstr
(
&
new_path
))
&&
(
git_futils_rmdir_r
(
git_buf_cstr
(
&
new_path
),
NULL
,
GIT_RMDIR_SKIP_NONEMPTY
)
<
0
))
{
error
=
-
1
;
goto
cleanup
;
}
if
(
git_futils_mkpath2file
(
git_buf_cstr
(
&
new_path
),
GIT_REFLOG_DIR_MODE
)
<
0
)
{
error
=
-
1
;
goto
cleanup
;
}
if
(
p_rename
(
git_buf_cstr
(
&
temp_path
),
git_buf_cstr
(
&
new_path
))
<
0
)
{
giterr_set
(
GITERR_OS
,
"Failed to rename reflog for %s"
,
new_name
);
error
=
-
1
;
}
cleanup:
git_buf_free
(
&
temp_path
);
git_buf_free
(
&
old_path
);
git_buf_free
(
&
new_path
);
git_buf_free
(
&
normalized
);
return
error
;
return
refdb
->
backend
->
reflog_rename
(
refdb
->
backend
,
old_name
,
new_name
);
}
int
git_reflog_delete
(
git_re
ference
*
ref
)
int
git_reflog_delete
(
git_re
pository
*
repo
,
const
char
*
name
)
{
git_refdb
*
refdb
;
int
error
;
git_buf
path
=
GIT_BUF_INIT
;
error
=
retrieve_reflog_path
(
&
path
,
ref
);
if
(
!
error
&&
git_path_exists
(
path
.
ptr
))
error
=
p_unlink
(
path
.
ptr
);
git_buf_free
(
&
path
);
if
((
error
=
git_repository_refdb__weakptr
(
&
refdb
,
repo
))
<
0
)
return
-
1
;
return
error
;
return
refdb
->
backend
->
reflog_delete
(
refdb
->
backend
,
name
)
;
}
size_t
git_reflog_entrycount
(
git_reflog
*
reflog
)
...
...
@@ -429,11 +148,6 @@ size_t git_reflog_entrycount(git_reflog *reflog)
return
reflog
->
entries
.
length
;
}
GIT_INLINE
(
size_t
)
reflog_inverse_index
(
size_t
idx
,
size_t
total
)
{
return
(
total
-
1
)
-
idx
;
}
const
git_reflog_entry
*
git_reflog_entry_byindex
(
git_reflog
*
reflog
,
size_t
idx
)
{
assert
(
reflog
);
...
...
@@ -469,26 +183,21 @@ const char * git_reflog_entry_message(const git_reflog_entry *entry)
return
entry
->
msg
;
}
int
git_reflog_drop
(
git_reflog
*
reflog
,
size_t
idx
,
int
rewrite_previous_entry
)
int
git_reflog_drop
(
git_reflog
*
reflog
,
size_t
idx
,
int
rewrite_previous_entry
)
{
size_t
entrycount
;
git_reflog_entry
*
entry
,
*
previous
;
assert
(
reflog
);
entrycount
=
git_reflog_entrycount
(
reflog
);
entry
=
(
git_reflog_entry
*
)
git_reflog_entry_byindex
(
reflog
,
idx
);
if
(
entry
==
NULL
)
{
giterr_set
(
GITERR_REFERENCE
,
"No reflog entry at index
%
"
PRIuZ
,
idx
);
giterr_set
(
GITERR_REFERENCE
,
"No reflog entry at index "
PRIuZ
,
idx
);
return
GIT_ENOTFOUND
;
}
reflog_entry
_free
(
entry
);
git_reflog_entry_
_free
(
entry
);
if
(
git_vector_remove
(
&
reflog
->
entries
,
reflog_inverse_index
(
idx
,
entrycount
))
<
0
)
...
...
@@ -521,3 +230,22 @@ int git_reflog_drop(
return
0
;
}
int
git_reflog_append_to
(
git_repository
*
repo
,
const
char
*
name
,
const
git_oid
*
id
,
const
git_signature
*
committer
,
const
char
*
msg
)
{
int
error
;
git_reflog
*
reflog
;
if
((
error
=
git_reflog_read
(
&
reflog
,
repo
,
name
))
<
0
)
return
error
;
if
((
error
=
git_reflog_append
(
reflog
,
id
,
committer
,
msg
))
<
0
)
goto
cleanup
;
error
=
git_reflog_write
(
reflog
);
cleanup:
git_reflog_free
(
reflog
);
return
error
;
}
src/reflog.h
View file @
8f4a8b09
...
...
@@ -27,9 +27,14 @@ struct git_reflog_entry {
};
struct
git_reflog
{
git_refdb
*
db
;
char
*
ref_name
;
git_repository
*
owner
;
git_vector
entries
;
};
GIT_INLINE
(
size_t
)
reflog_inverse_index
(
size_t
idx
,
size_t
total
)
{
return
(
total
-
1
)
-
idx
;
}
#endif
/* INCLUDE_reflog_h__ */
src/refs.c
View file @
8f4a8b09
...
...
@@ -483,7 +483,7 @@ int git_reference_rename(
if
(
reference_has_log
<
0
)
return
reference_has_log
;
if
(
reference_has_log
&&
(
error
=
git_reflog_rename
(
ref
,
new_name
))
<
0
)
if
(
reference_has_log
&&
(
error
=
git_reflog_rename
(
git_reference_owner
(
ref
),
git_reference_name
(
ref
)
,
new_name
))
<
0
)
return
error
;
return
0
;
...
...
src/revparse.c
View file @
8f4a8b09
...
...
@@ -160,7 +160,7 @@ static int retrieve_previously_checked_out_branch_or_revision(git_object **out,
if
(
git_reference_lookup
(
&
ref
,
repo
,
GIT_HEAD_FILE
)
<
0
)
goto
cleanup
;
if
(
git_reflog_read
(
&
reflog
,
re
f
)
<
0
)
if
(
git_reflog_read
(
&
reflog
,
re
po
,
GIT_HEAD_FILE
)
<
0
)
goto
cleanup
;
numentries
=
git_reflog_entrycount
(
reflog
);
...
...
@@ -208,7 +208,7 @@ static int retrieve_oid_from_reflog(git_oid *oid, git_reference *ref, size_t ide
const
git_reflog_entry
*
entry
;
bool
search_by_pos
=
(
identifier
<=
100000000
);
if
(
git_reflog_read
(
&
reflog
,
ref
)
<
0
)
if
(
git_reflog_read
(
&
reflog
,
git_reference_owner
(
ref
),
git_reference_name
(
ref
)
)
<
0
)
return
-
1
;
numentries
=
git_reflog_entrycount
(
reflog
);
...
...
src/stash.c
View file @
8f4a8b09
...
...
@@ -411,14 +411,16 @@ static int update_reflog(
const
git_signature
*
stasher
,
const
char
*
message
)
{
git_reference
*
stash
=
NULL
;
git_reference
*
stash
;
git_reflog
*
reflog
=
NULL
;
int
error
;
if
((
error
=
git_reference_create
(
&
stash
,
repo
,
GIT_REFS_STASH_FILE
,
w_commit_oid
,
1
))
<
0
)
goto
cleanup
;
if
((
error
=
git_reflog_read
(
&
reflog
,
stash
))
<
0
)
git_reference_free
(
stash
);
if
((
error
=
git_reflog_read
(
&
reflog
,
repo
,
GIT_REFS_STASH_FILE
)
<
0
))
goto
cleanup
;
if
((
error
=
git_reflog_append
(
reflog
,
w_commit_oid
,
stasher
,
message
))
<
0
)
...
...
@@ -428,7 +430,6 @@ static int update_reflog(
goto
cleanup
;
cleanup:
git_reference_free
(
stash
);
git_reflog_free
(
reflog
);
return
error
;
}
...
...
@@ -574,7 +575,7 @@ int git_stash_foreach(
if
(
error
<
0
)
goto
cleanup
;
if
((
error
=
git_reflog_read
(
&
reflog
,
stash
))
<
0
)
if
((
error
=
git_reflog_read
(
&
reflog
,
repo
,
GIT_REFS_STASH_FILE
))
<
0
)
goto
cleanup
;
max
=
git_reflog_entrycount
(
reflog
);
...
...
@@ -608,7 +609,7 @@ int git_stash_drop(
if
((
error
=
git_reference_lookup
(
&
stash
,
repo
,
GIT_REFS_STASH_FILE
))
<
0
)
return
error
;
if
((
error
=
git_reflog_read
(
&
reflog
,
stash
))
<
0
)
if
((
error
=
git_reflog_read
(
&
reflog
,
repo
,
GIT_REFS_STASH_FILE
))
<
0
)
goto
cleanup
;
max
=
git_reflog_entrycount
(
reflog
);
...
...
tests-clar/refs/reflog/drop.c
View file @
8f4a8b09
...
...
@@ -8,15 +8,10 @@ static size_t 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
);
git_reflog_read
(
&
g_reflog
,
g_repo
,
"HEAD"
);
entrycount
=
git_reflog_entrycount
(
g_reflog
);
git_reference_free
(
ref
);
}
void
test_refs_reflog_drop__cleanup
(
void
)
...
...
@@ -106,19 +101,15 @@ void test_refs_reflog_drop__can_drop_all_the_entries(void)
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_drop
(
g_reflog
,
0
,
1
));
cl_assert_equal_sz
(
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
);
git_reflog_read
(
&
g_reflog
,
g_repo
,
"HEAD"
);
cl_assert_equal_sz
(
entrycount
-
1
,
git_reflog_entrycount
(
g_reflog
));
}
tests-clar/refs/reflog/reflog.c
View file @
8f4a8b09
...
...
@@ -13,7 +13,7 @@ static git_repository *g_repo;
// helpers
static
void
assert_signature
(
git_signature
*
expected
,
git_signature
*
actual
)
static
void
assert_signature
(
const
git_signature
*
expected
,
const
git_signature
*
actual
)
{
cl_assert
(
actual
);
cl_assert_equal_s
(
expected
->
name
,
actual
->
name
);
...
...
@@ -34,30 +34,13 @@ void test_refs_reflog_reflog__cleanup(void)
cl_git_sandbox_cleanup
();
}
void
test_refs_reflog_reflog__append_then_read
(
v
oid
)
static
void
assert_appends
(
const
git_signature
*
committer
,
const
git_oid
*
oid
)
{
// write a reflog for a given reference and ensure it can be read back
git_repository
*
repo2
;
git_reference
*
ref
,
*
lookedup_ref
;
git_oid
oid
;
git_signature
*
committer
;
git_reference
*
lookedup_ref
;
git_reflog
*
reflog
;
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
(
&
ref
,
g_repo
,
new_ref
,
&
oid
,
0
));
cl_git_pass
(
git_signature_now
(
&
committer
,
"foo"
,
"foo@bar"
));
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"
));
...
...
@@ -65,29 +48,78 @@ void test_refs_reflog_reflog__append_then_read(void)
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_git_pass
(
git_reflog_read
(
&
reflog
,
repo2
,
new
_ref
));
cl_assert_equal_i
(
2
,
(
int
)
git_reflog_entrycount
(
reflog
));
entry
=
git_reflog_entry_byindex
(
reflog
,
1
);
assert_signature
(
committer
,
entry
->
committer
);
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
(
git_oid_cmp
(
oid
,
&
entry
->
oid_cur
)
==
0
);
cl_assert
(
entry
->
msg
==
NULL
);
entry
=
git_reflog_entry_byindex
(
reflog
,
0
);
assert_signature
(
committer
,
entry
->
committer
);
cl_assert
(
git_oid_cmp
(
&
oid
,
&
entry
->
oid_old
)
==
0
);
cl_assert
(
git_oid_cmp
(
&
oid
,
&
entry
->
oid_cur
)
==
0
);
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
);
git_reflog_free
(
reflog
);
git_repository_free
(
repo2
);
git_reference_free
(
ref
);
git_reference_free
(
lookedup_ref
);
}
void
test_refs_reflog_reflog__append_then_read
(
void
)
{
/* write a reflog for a given reference and ensure it can be read back */
git_reference
*
ref
;
git_oid
oid
;
git_signature
*
committer
;
git_reflog
*
reflog
;
/* Create a new branch pointing at the HEAD */
git_oid_fromstr
(
&
oid
,
current_master_tip
);
cl_git_pass
(
git_reference_create
(
&
ref
,
g_repo
,
new_ref
,
&
oid
,
0
));
git_reference_free
(
ref
);
cl_git_pass
(
git_signature_now
(
&
committer
,
"foo"
,
"foo@bar"
));
cl_git_pass
(
git_reflog_read
(
&
reflog
,
g_repo
,
new_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
);
assert_appends
(
committer
,
&
oid
);
git_signature_free
(
committer
);
}
void
test_refs_reflog_reflog__append_to_then_read
(
void
)
{
/* write a reflog for a given reference and ensure it can be read back */
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
(
&
ref
,
g_repo
,
new_ref
,
&
oid
,
0
));
git_reference_free
(
ref
);
cl_git_pass
(
git_signature_now
(
&
committer
,
"foo"
,
"foo@bar"
));
cl_git_fail
(
git_reflog_append_to
(
g_repo
,
new_ref
,
&
oid
,
committer
,
"no inner
\n
newline"
));
cl_git_pass
(
git_reflog_append_to
(
g_repo
,
new_ref
,
&
oid
,
committer
,
NULL
));
cl_git_pass
(
git_reflog_append_to
(
g_repo
,
new_ref
,
&
oid
,
committer
,
commit_msg
"
\n
"
));
assert_appends
(
committer
,
&
oid
);
git_signature_free
(
committer
);
}
void
test_refs_reflog_reflog__renaming_the_reference_moves_the_reflog
(
void
)
{
git_reference
*
master
,
*
new_master
;
...
...
@@ -133,21 +165,18 @@ void test_refs_reflog_reflog__reference_has_reflog(void)
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
;
const
char
*
refname
=
"refs/heads/subtrees"
;
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
));
git_buf_join_n
(
&
subtrees_log_path
,
'/'
,
3
,
git_repository_path
(
g_repo
),
GIT_REFLOG_DIR
,
refname
);
cl_assert_equal_i
(
false
,
git_path_isfile
(
git_buf_cstr
(
&
subtrees_log_path
)));
cl_git_pass
(
git_reflog_read
(
&
reflog
,
subtrees
));
cl_git_pass
(
git_reflog_read
(
&
reflog
,
g_repo
,
refname
));
cl_assert_equal_i
(
0
,
(
int
)
git_reflog_entrycount
(
reflog
));
git_reflog_free
(
reflog
);
git_reference_free
(
subtrees
);
git_buf_free
(
&
subtrees_log_path
);
}
...
...
@@ -158,7 +187,7 @@ void test_refs_reflog_reflog__cannot_write_a_moved_reflog(void)
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_read
(
&
reflog
,
g_repo
,
"refs/heads/master"
));
cl_git_pass
(
git_reflog_write
(
reflog
));
...
...
@@ -175,12 +204,6 @@ void test_refs_reflog_reflog__cannot_write_a_moved_reflog(void)
void
test_refs_reflog_reflog__renaming_with_an_invalid_name_returns_EINVALIDSPEC
(
void
)
{
git_reference
*
master
;
cl_git_pass
(
git_reference_lookup
(
&
master
,
g_repo
,
"refs/heads/master"
));
cl_assert_equal_i
(
GIT_EINVALIDSPEC
,
git_reflog_rename
(
master
,
"refs/heads/Inv@{id"
));
git_reference_free
(
master
);
git_reflog_rename
(
g_repo
,
"refs/heads/master"
,
"refs/heads/Inv@{id"
));
}
tests-clar/stash/drop.c
View file @
8f4a8b09
...
...
@@ -102,7 +102,7 @@ void test_stash_drop__dropping_an_entry_rewrites_reflog_history(void)
cl_git_pass
(
git_reference_lookup
(
&
stash
,
repo
,
GIT_REFS_STASH_FILE
));
cl_git_pass
(
git_reflog_read
(
&
reflog
,
stash
));
cl_git_pass
(
git_reflog_read
(
&
reflog
,
repo
,
GIT_REFS_STASH_FILE
));
entry
=
git_reflog_entry_byindex
(
reflog
,
1
);
git_oid_cpy
(
&
oid
,
git_reflog_entry_id_old
(
entry
));
...
...
@@ -112,7 +112,7 @@ void test_stash_drop__dropping_an_entry_rewrites_reflog_history(void)
cl_git_pass
(
git_stash_drop
(
repo
,
1
));
cl_git_pass
(
git_reflog_read
(
&
reflog
,
stash
));
cl_git_pass
(
git_reflog_read
(
&
reflog
,
repo
,
GIT_REFS_STASH_FILE
));
entry
=
git_reflog_entry_byindex
(
reflog
,
0
);
cl_assert_equal_i
(
0
,
git_oid_cmp
(
&
oid
,
git_reflog_entry_id_old
(
entry
)));
...
...
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