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
a35a9890
Commit
a35a9890
authored
Jul 17, 2014
by
Edward Thomson
Committed by
Edward Thomson
Oct 26, 2014
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Introduce git_rebase_commit
Commit the current patch of a rebase process.
parent
443d5674
Show whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
241 additions
and
11 deletions
+241
-11
include/git2/rebase.h
+28
-0
src/rebase.c
+110
-11
src/signature.c
+11
-0
src/signature.h
+1
-0
tests/rebase/merge.c
+91
-0
No files found.
include/git2/rebase.h
View file @
a35a9890
...
...
@@ -82,6 +82,34 @@ GIT_EXTERN(int) git_rebase_next(
git_checkout_options
*
checkout_opts
);
/**
* Commits the current patch. You must have resolved any conflicts that
* were introduced during the patch application from the `git_rebase_next`
* invocation.
*
* @param id Pointer in which to store the OID of the newly created commit
* @param repo The repository with the in-progress rebase
* @param author The author of the updated commit, or NULL to keep the
* author from the original commit
* @param committer The committer of the rebase
* @param message_encoding The encoding for the message in the commit,
* represented with a standard encoding name. If message is NULL,
* this should also be NULL, and the encoding from the original
* commit will be maintained. If message is specified, this may be
* NULL to indicate that "UTF-8" is to be used.
* @param message The message for this commit, or NULL to keep the message
* from the original commit
* @return Zero on success, GIT_EUNMERGED if there are unmerged changes in
* the index, -1 on failure.
*/
GIT_EXTERN
(
int
)
git_rebase_commit
(
git_oid
*
id
,
git_repository
*
repo
,
const
git_signature
*
author
,
const
git_signature
*
committer
,
const
char
*
message_encoding
,
const
char
*
message
);
/**
* Aborts a rebase that is currently in progress, resetting the repository
* and working directory to their state before rebase began.
*
...
...
src/rebase.c
View file @
a35a9890
...
...
@@ -33,6 +33,7 @@
#define END_FILE "end"
#define CMT_FILE_FMT "cmt.%d"
#define CURRENT_FILE "current"
#define REWRITTEN_FILE "rewritten"
#define ORIG_DETACHED_HEAD "detached HEAD"
...
...
@@ -284,7 +285,7 @@ static int rebase_finish(git_rebase_state *state)
0
;
}
static
int
rebase_setupfile
(
git_repository
*
repo
,
const
char
*
filename
,
const
char
*
fmt
,
...)
static
int
rebase_setupfile
(
git_repository
*
repo
,
const
char
*
filename
,
int
flags
,
const
char
*
fmt
,
...)
{
git_buf
path
=
GIT_BUF_INIT
,
contents
=
GIT_BUF_INIT
;
...
...
@@ -297,7 +298,7 @@ static int rebase_setupfile(git_repository *repo, const char *filename, const ch
if
((
error
=
git_buf_joinpath
(
&
path
,
repo
->
path_repository
,
REBASE_MERGE_DIR
))
==
0
&&
(
error
=
git_buf_joinpath
(
&
path
,
path
.
ptr
,
filename
))
==
0
)
error
=
git_futils_writebuffer
(
&
contents
,
path
.
ptr
,
O_RDWR
|
O_CREAT
,
REBASE_FILE_MODE
);
error
=
git_futils_writebuffer
(
&
contents
,
path
.
ptr
,
flags
,
REBASE_FILE_MODE
);
git_buf_free
(
&
path
);
git_buf_free
(
&
contents
);
...
...
@@ -361,16 +362,16 @@ static int rebase_setup_merge(
git_buf_printf
(
&
commit_filename
,
CMT_FILE_FMT
,
commit_cnt
);
git_oid_fmt
(
id_str
,
&
id
);
if
((
error
=
rebase_setupfile
(
repo
,
commit_filename
.
ptr
,
if
((
error
=
rebase_setupfile
(
repo
,
commit_filename
.
ptr
,
-
1
,
"%.*s
\n
"
,
GIT_OID_HEXSZ
,
id_str
))
<
0
)
goto
done
;
}
if
(
error
!=
GIT_ITEROVER
||
(
error
=
rebase_setupfile
(
repo
,
END_FILE
,
"%d
\n
"
,
commit_cnt
))
<
0
)
(
error
=
rebase_setupfile
(
repo
,
END_FILE
,
-
1
,
"%d
\n
"
,
commit_cnt
))
<
0
)
goto
done
;
error
=
rebase_setupfile
(
repo
,
ONTO_NAME_FILE
,
"%s
\n
"
,
error
=
rebase_setupfile
(
repo
,
ONTO_NAME_FILE
,
-
1
,
"%s
\n
"
,
rebase_onto_name
(
onto
));
done:
...
...
@@ -405,10 +406,10 @@ static int rebase_setup(
orig_head_name
=
branch
->
ref_name
?
branch
->
ref_name
:
ORIG_DETACHED_HEAD
;
if
((
error
=
rebase_setupfile
(
repo
,
HEAD_NAME_FILE
,
"%s
\n
"
,
orig_head_name
))
<
0
||
(
error
=
rebase_setupfile
(
repo
,
ONTO_FILE
,
"%s
\n
"
,
onto
->
oid_str
))
<
0
||
(
error
=
rebase_setupfile
(
repo
,
ORIG_HEAD_FILE
,
"%s
\n
"
,
branch
->
oid_str
))
<
0
||
(
error
=
rebase_setupfile
(
repo
,
QUIET_FILE
,
opts
->
quiet
?
"t
\n
"
:
"
\n
"
))
<
0
)
if
((
error
=
rebase_setupfile
(
repo
,
HEAD_NAME_FILE
,
-
1
,
"%s
\n
"
,
orig_head_name
))
<
0
||
(
error
=
rebase_setupfile
(
repo
,
ONTO_FILE
,
-
1
,
"%s
\n
"
,
onto
->
oid_str
))
<
0
||
(
error
=
rebase_setupfile
(
repo
,
ORIG_HEAD_FILE
,
-
1
,
"%s
\n
"
,
branch
->
oid_str
))
<
0
||
(
error
=
rebase_setupfile
(
repo
,
QUIET_FILE
,
-
1
,
opts
->
quiet
?
"t
\n
"
:
"
\n
"
))
<
0
)
goto
done
;
error
=
rebase_setup_merge
(
repo
,
branch
,
upstream
,
onto
,
opts
);
...
...
@@ -615,8 +616,8 @@ static int rebase_next_merge(
goto
done
;
}
if
((
error
=
rebase_setupfile
(
repo
,
MSGNUM_FILE
,
"%d
\n
"
,
state
->
merge
.
msgnum
))
<
0
||
(
error
=
rebase_setupfile
(
repo
,
CURRENT_FILE
,
"%s
\n
"
,
current
.
ptr
))
<
0
)
if
((
error
=
rebase_setupfile
(
repo
,
MSGNUM_FILE
,
-
1
,
"%d
\n
"
,
state
->
merge
.
msgnum
))
<
0
||
(
error
=
rebase_setupfile
(
repo
,
CURRENT_FILE
,
-
1
,
"%s
\n
"
,
current
.
ptr
))
<
0
)
goto
done
;
if
((
error
=
normalize_checkout_opts
(
repo
,
&
checkout_opts
,
given_checkout_opts
,
state
))
<
0
||
...
...
@@ -661,6 +662,104 @@ int git_rebase_next(
return
error
;
}
static
int
rebase_commit_merge
(
git_oid
*
commit_id
,
git_repository
*
repo
,
git_rebase_state
*
state
,
const
git_signature
*
author
,
const
git_signature
*
committer
,
const
char
*
message_encoding
,
const
char
*
message
)
{
git_index
*
index
=
NULL
;
git_reference
*
head
=
NULL
;
git_commit
*
head_commit
=
NULL
;
git_tree
*
tree
=
NULL
;
git_oid
tree_id
;
char
old_idstr
[
GIT_OID_HEXSZ
],
new_idstr
[
GIT_OID_HEXSZ
];
int
error
;
if
(
!
state
->
merge
.
msgnum
||
!
state
->
merge
.
current
)
{
giterr_set
(
GITERR_REBASE
,
"No rebase-merge state files exist"
);
error
=
-
1
;
goto
done
;
}
if
((
error
=
git_repository_index
(
&
index
,
repo
))
<
0
)
goto
done
;
if
(
git_index_has_conflicts
(
index
))
{
giterr_set
(
GITERR_REBASE
,
"Conflicts have not been resolved"
);
error
=
GIT_EMERGECONFLICT
;
goto
done
;
}
/* TODO: if there are no changes, error with a useful code */
if
((
error
=
git_repository_head
(
&
head
,
repo
))
<
0
||
(
error
=
git_reference_peel
((
git_object
**
)
&
head_commit
,
head
,
GIT_OBJ_COMMIT
))
<
0
||
(
error
=
git_index_write_tree
(
&
tree_id
,
index
))
<
0
||
(
error
=
git_tree_lookup
(
&
tree
,
repo
,
&
tree_id
))
<
0
)
goto
done
;
if
(
!
author
)
author
=
git_commit_author
(
state
->
merge
.
current
);
if
(
!
message
)
{
message_encoding
=
git_commit_message_encoding
(
state
->
merge
.
current
);
message
=
git_commit_message
(
state
->
merge
.
current
);
}
if
((
error
=
git_commit_create
(
commit_id
,
repo
,
"HEAD"
,
author
,
committer
,
message_encoding
,
message
,
tree
,
1
,
(
const
git_commit
**
)
&
head_commit
))
<
0
)
goto
done
;
git_oid_fmt
(
old_idstr
,
git_commit_id
(
state
->
merge
.
current
));
git_oid_fmt
(
new_idstr
,
commit_id
);
error
=
rebase_setupfile
(
repo
,
REWRITTEN_FILE
,
O_CREAT
|
O_WRONLY
|
O_APPEND
,
"%.*s %.*s
\n
"
,
GIT_OID_HEXSZ
,
old_idstr
,
GIT_OID_HEXSZ
,
new_idstr
);
done:
git_tree_free
(
tree
);
git_commit_free
(
head_commit
);
git_reference_free
(
head
);
git_index_free
(
index
);
return
error
;
}
int
git_rebase_commit
(
git_oid
*
id
,
git_repository
*
repo
,
const
git_signature
*
author
,
const
git_signature
*
committer
,
const
char
*
message_encoding
,
const
char
*
message
)
{
git_rebase_state
state
=
GIT_REBASE_STATE_INIT
;
int
error
;
assert
(
repo
&&
committer
);
if
((
error
=
rebase_state
(
&
state
,
repo
))
<
0
)
goto
done
;
switch
(
state
.
type
)
{
case
GIT_REBASE_TYPE_MERGE
:
error
=
rebase_commit_merge
(
id
,
repo
,
&
state
,
author
,
committer
,
message_encoding
,
message
);
break
;
default:
abort
();
}
done:
rebase_state_free
(
&
state
);
return
error
;
}
int
git_rebase_abort
(
git_repository
*
repo
,
const
git_signature
*
signature
)
{
git_rebase_state
state
=
GIT_REBASE_STATE_INIT
;
...
...
src/signature.c
View file @
a35a9890
...
...
@@ -270,3 +270,14 @@ void git_signature__writebuf(git_buf *buf, const char *header, const git_signatu
(
unsigned
)
sig
->
when
.
time
,
sign
,
hours
,
mins
);
}
bool
git_signature__equal
(
const
git_signature
*
one
,
const
git_signature
*
two
)
{
assert
(
one
&&
two
);
return
git__strcmp
(
one
->
name
,
two
->
name
)
==
0
&&
git__strcmp
(
one
->
email
,
two
->
email
)
==
0
&&
one
->
when
.
time
==
two
->
when
.
time
&&
one
->
when
.
offset
==
two
->
when
.
offset
;
}
src/signature.h
View file @
a35a9890
...
...
@@ -14,6 +14,7 @@
int
git_signature__parse
(
git_signature
*
sig
,
const
char
**
buffer_out
,
const
char
*
buffer_end
,
const
char
*
header
,
char
ender
);
void
git_signature__writebuf
(
git_buf
*
buf
,
const
char
*
header
,
const
git_signature
*
sig
);
bool
git_signature__equal
(
const
git_signature
*
one
,
const
git_signature
*
two
);
int
git_signature__pdup
(
git_signature
**
dest
,
const
git_signature
*
source
,
git_pool
*
pool
);
...
...
tests/rebase/merge.c
View file @
a35a9890
#include "clar_libgit2.h"
#include "git2/rebase.h"
#include "posix.h"
#include "signature.h"
#include <fcntl.h>
...
...
@@ -11,10 +12,13 @@ static git_signature *signature;
void
test_rebase_merge__initialize
(
void
)
{
repo
=
cl_git_sandbox_init
(
"rebase"
);
cl_git_pass
(
git_signature_new
(
&
signature
,
"Rebaser"
,
"rebaser@rebaser.rb"
,
1405694510
,
0
));
}
void
test_rebase_merge__cleanup
(
void
)
{
git_signature_free
(
signature
);
cl_git_sandbox_cleanup
();
}
...
...
@@ -116,3 +120,90 @@ void test_rebase_merge__next_with_conflicts(void)
git_reference_free
(
upstream_ref
);
}
void
test_rebase_merge__commit
(
void
)
{
git_reference
*
branch_ref
,
*
upstream_ref
;
git_merge_head
*
branch_head
,
*
upstream_head
;
git_checkout_options
checkout_opts
=
GIT_CHECKOUT_OPTIONS_INIT
;
git_oid
commit_id
,
tree_id
,
parent_id
;
git_signature
*
author
;
git_commit
*
commit
;
checkout_opts
.
checkout_strategy
=
GIT_CHECKOUT_SAFE
;
cl_git_pass
(
git_reference_lookup
(
&
branch_ref
,
repo
,
"refs/heads/beef"
));
cl_git_pass
(
git_reference_lookup
(
&
upstream_ref
,
repo
,
"refs/heads/master"
));
cl_git_pass
(
git_merge_head_from_ref
(
&
branch_head
,
repo
,
branch_ref
));
cl_git_pass
(
git_merge_head_from_ref
(
&
upstream_head
,
repo
,
upstream_ref
));
cl_git_pass
(
git_rebase
(
repo
,
branch_head
,
upstream_head
,
NULL
,
signature
,
NULL
));
cl_git_pass
(
git_rebase_next
(
repo
,
&
checkout_opts
));
cl_git_pass
(
git_rebase_commit
(
&
commit_id
,
repo
,
NULL
,
signature
,
NULL
,
NULL
));
cl_git_pass
(
git_commit_lookup
(
&
commit
,
repo
,
&
commit_id
));
git_oid_fromstr
(
&
parent_id
,
"efad0b11c47cb2f0220cbd6f5b0f93bb99064b00"
);
cl_assert_equal_i
(
1
,
git_commit_parentcount
(
commit
));
cl_assert_equal_oid
(
&
parent_id
,
git_commit_parent_id
(
commit
,
0
));
git_oid_fromstr
(
&
tree_id
,
"4461379789c777d2a6c1f2ee0e9d6c86731b9992"
);
cl_assert_equal_oid
(
&
tree_id
,
git_commit_tree_id
(
commit
));
cl_assert_equal_s
(
NULL
,
git_commit_message_encoding
(
commit
));
cl_assert_equal_s
(
"Modification 1 to beef
\n
"
,
git_commit_message
(
commit
));
cl_git_pass
(
git_signature_new
(
&
author
,
"Edward Thomson"
,
"ethomson@edwardthomson.com"
,
1405621769
,
0
-
(
4
*
60
)));
cl_assert
(
git_signature__equal
(
author
,
git_commit_author
(
commit
)));
cl_assert
(
git_signature__equal
(
signature
,
git_commit_committer
(
commit
)));
cl_assert_equal_file
(
"da9c51a23d02d931a486f45ad18cda05cf5d2b94 776e4c48922799f903f03f5f6e51da8b01e4cce0
\n
"
,
82
,
"rebase/.git/rebase-merge/rewritten"
);
git_signature_free
(
author
);
git_commit_free
(
commit
);
git_merge_head_free
(
branch_head
);
git_merge_head_free
(
upstream_head
);
git_reference_free
(
branch_ref
);
git_reference_free
(
upstream_ref
);
}
void
test_rebase_merge__commit_updates_rewritten
(
void
)
{
git_reference
*
branch_ref
,
*
upstream_ref
;
git_merge_head
*
branch_head
,
*
upstream_head
;
git_checkout_options
checkout_opts
=
GIT_CHECKOUT_OPTIONS_INIT
;
git_oid
commit_id
;
checkout_opts
.
checkout_strategy
=
GIT_CHECKOUT_SAFE
;
cl_git_pass
(
git_reference_lookup
(
&
branch_ref
,
repo
,
"refs/heads/beef"
));
cl_git_pass
(
git_reference_lookup
(
&
upstream_ref
,
repo
,
"refs/heads/master"
));
cl_git_pass
(
git_merge_head_from_ref
(
&
branch_head
,
repo
,
branch_ref
));
cl_git_pass
(
git_merge_head_from_ref
(
&
upstream_head
,
repo
,
upstream_ref
));
cl_git_pass
(
git_rebase
(
repo
,
branch_head
,
upstream_head
,
NULL
,
signature
,
NULL
));
cl_git_pass
(
git_rebase_next
(
repo
,
&
checkout_opts
));
cl_git_pass
(
git_rebase_commit
(
&
commit_id
,
repo
,
NULL
,
signature
,
NULL
,
NULL
));
cl_git_pass
(
git_rebase_next
(
repo
,
&
checkout_opts
));
cl_git_pass
(
git_rebase_commit
(
&
commit_id
,
repo
,
NULL
,
signature
,
NULL
,
NULL
));
cl_assert_equal_file
(
"da9c51a23d02d931a486f45ad18cda05cf5d2b94 776e4c48922799f903f03f5f6e51da8b01e4cce0
\n
"
"8d1f13f93c4995760ac07d129246ac1ff64c0be9 ba1f9b4fd5cf8151f7818be2111cc0869f1eb95a
\n
"
,
164
,
"rebase/.git/rebase-merge/rewritten"
);
git_merge_head_free
(
branch_head
);
git_merge_head_free
(
upstream_head
);
git_reference_free
(
branch_ref
);
git_reference_free
(
upstream_ref
);
}
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