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
c30955e0
Commit
c30955e0
authored
Apr 26, 2016
by
Carlos Martín Nieto
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #3748 from libgit2/ethomson/rebase_detached
Rebase improvements with IDs
parents
b058297a
1f84caf0
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
161 additions
and
32 deletions
+161
-32
src/rebase.c
+46
-27
tests/rebase/abort.c
+65
-5
tests/rebase/merge.c
+50
-0
No files found.
src/rebase.c
View file @
c30955e0
...
...
@@ -472,6 +472,7 @@ done:
static
int
rebase_setupfiles
(
git_rebase
*
rebase
)
{
char
onto
[
GIT_OID_HEXSZ
],
orig_head
[
GIT_OID_HEXSZ
];
const
char
*
orig_head_name
;
git_oid_fmt
(
onto
,
&
rebase
->
onto_id
);
git_oid_fmt
(
orig_head
,
&
rebase
->
orig_head_id
);
...
...
@@ -481,8 +482,11 @@ static int rebase_setupfiles(git_rebase *rebase)
return
-
1
;
}
orig_head_name
=
rebase
->
head_detached
?
ORIG_DETACHED_HEAD
:
rebase
->
orig_head_name
;
if
(
git_repository__set_orig_head
(
rebase
->
repo
,
&
rebase
->
orig_head_id
)
<
0
||
rebase_setupfile
(
rebase
,
HEAD_NAME_FILE
,
-
1
,
"%s
\n
"
,
rebase
->
orig_head_name
)
<
0
||
rebase_setupfile
(
rebase
,
HEAD_NAME_FILE
,
-
1
,
"%s
\n
"
,
orig_head_name
)
<
0
||
rebase_setupfile
(
rebase
,
ONTO_FILE
,
-
1
,
"%.*s
\n
"
,
GIT_OID_HEXSZ
,
onto
)
<
0
||
rebase_setupfile
(
rebase
,
ORIG_HEAD_FILE
,
-
1
,
"%.*s
\n
"
,
GIT_OID_HEXSZ
,
orig_head
)
<
0
||
rebase_setupfile
(
rebase
,
QUIET_FILE
,
-
1
,
rebase
->
quiet
?
"t
\n
"
:
"
\n
"
)
<
0
)
...
...
@@ -626,8 +630,12 @@ static int rebase_init_merge(
rebase
->
state_path
=
git_buf_detach
(
&
state_path
);
GITERR_CHECK_ALLOC
(
rebase
->
state_path
);
rebase
->
orig_head_name
=
git__strdup
(
branch
->
ref_name
?
branch
->
ref_name
:
ORIG_DETACHED_HEAD
);
GITERR_CHECK_ALLOC
(
rebase
->
orig_head_name
);
if
(
branch
->
ref_name
)
{
rebase
->
orig_head_name
=
git__strdup
(
branch
->
ref_name
);
GITERR_CHECK_ALLOC
(
rebase
->
orig_head_name
);
}
else
{
rebase
->
head_detached
=
1
;
}
rebase
->
onto_name
=
git__strdup
(
rebase_onto_name
(
onto
));
GITERR_CHECK_ALLOC
(
rebase
->
onto_name
);
...
...
@@ -1254,42 +1262,33 @@ done:
return
error
;
}
int
git_rebase_finish
(
git_rebase
*
rebase
,
const
git_signature
*
signature
)
static
int
return_to_orig_head
(
git_rebase
*
rebase
)
{
git_reference
*
terminal_ref
=
NULL
,
*
branch_ref
=
NULL
,
*
head_ref
=
NULL
;
git_commit
*
terminal_commit
=
NULL
;
git_buf
branch_msg
=
GIT_BUF_INIT
,
head_msg
=
GIT_BUF_INIT
;
char
onto
[
GIT_OID_HEXSZ
];
int
error
;
assert
(
rebase
);
if
(
rebase
->
inmemory
)
return
0
;
int
error
=
0
;
git_oid_fmt
(
onto
,
&
rebase
->
onto_id
);
if
((
error
=
git_buf_printf
(
&
branch_msg
,
"rebase finished: %s onto %.*s"
,
rebase
->
orig_head_name
,
GIT_OID_HEXSZ
,
onto
))
<
0
||
(
error
=
git_buf_printf
(
&
head_msg
,
"rebase finished: returning to %s"
,
rebase
->
orig_head_name
))
<
0
||
(
error
=
git_repository_head
(
&
terminal_ref
,
rebase
->
repo
))
<
0
||
if
((
error
=
git_buf_printf
(
&
branch_msg
,
"rebase finished: %s onto %.*s"
,
rebase
->
orig_head_name
,
GIT_OID_HEXSZ
,
onto
))
==
0
&&
(
error
=
git_buf_printf
(
&
head_msg
,
"rebase finished: returning to %s"
,
rebase
->
orig_head_name
))
==
0
&&
(
error
=
git_repository_head
(
&
terminal_ref
,
rebase
->
repo
))
==
0
&&
(
error
=
git_reference_peel
((
git_object
**
)
&
terminal_commit
,
terminal_ref
,
GIT_OBJ_COMMIT
))
<
0
||
terminal_ref
,
GIT_OBJ_COMMIT
))
==
0
&&
(
error
=
git_reference_create_matching
(
&
branch_ref
,
rebase
->
repo
,
rebase
->
orig_head_name
,
git_commit_id
(
terminal_commit
),
1
,
&
rebase
->
orig_head_id
,
branch_msg
.
ptr
))
<
0
||
(
error
=
git_reference_symbolic_create
(
&
head_ref
,
rebase
->
repo
,
rebase
->
orig_head_name
,
git_commit_id
(
terminal_commit
),
1
,
&
rebase
->
orig_head_id
,
branch_msg
.
ptr
))
==
0
)
error
=
git_reference_symbolic_create
(
&
head_ref
,
rebase
->
repo
,
GIT_HEAD_FILE
,
rebase
->
orig_head_name
,
1
,
head_msg
.
ptr
))
<
0
||
(
error
=
rebase_copy_notes
(
rebase
,
signature
))
<
0
)
goto
done
;
error
=
rebase_cleanup
(
rebase
);
head_msg
.
ptr
);
done
:
git_buf_free
(
&
head_msg
);
git_buf_free
(
&
branch_msg
);
git_commit_free
(
terminal_commit
);
...
...
@@ -1300,6 +1299,26 @@ done:
return
error
;
}
int
git_rebase_finish
(
git_rebase
*
rebase
,
const
git_signature
*
signature
)
{
int
error
=
0
;
assert
(
rebase
);
if
(
rebase
->
inmemory
)
return
0
;
if
(
!
rebase
->
head_detached
)
error
=
return_to_orig_head
(
rebase
);
if
(
error
==
0
&&
(
error
=
rebase_copy_notes
(
rebase
,
signature
))
==
0
)
error
=
rebase_cleanup
(
rebase
);
return
error
;
}
size_t
git_rebase_operation_entrycount
(
git_rebase
*
rebase
)
{
assert
(
rebase
);
...
...
tests/rebase/abort.c
View file @
c30955e0
...
...
@@ -19,17 +19,15 @@ void test_rebase_abort__cleanup(void)
cl_git_sandbox_cleanup
();
}
static
void
test_abort
(
git_annotated_commit
*
branch
,
git_annotated_commit
*
onto
)
static
void
ensure_aborted
(
git_annotated_commit
*
branch
,
git_annotated_commit
*
onto
)
{
git_rebase
*
rebase
;
git_reference
*
head_ref
,
*
branch_ref
=
NULL
;
git_status_list
*
statuslist
;
git_reflog
*
reflog
;
const
git_reflog_entry
*
reflog_entry
;
cl_git_pass
(
git_rebase_open
(
&
rebase
,
repo
,
NULL
));
cl_git_pass
(
git_rebase_abort
(
rebase
));
cl_assert_equal_i
(
GIT_REPOSITORY_STATE_NONE
,
git_repository_state
(
repo
));
/* Make sure the refs are updated appropriately */
...
...
@@ -58,6 +56,18 @@ static void test_abort(git_annotated_commit *branch, git_annotated_commit *onto)
git_reflog_free
(
reflog
);
git_reference_free
(
head_ref
);
git_reference_free
(
branch_ref
);
}
static
void
test_abort
(
git_annotated_commit
*
branch
,
git_annotated_commit
*
onto
)
{
git_rebase
*
rebase
;
cl_git_pass
(
git_rebase_open
(
&
rebase
,
repo
,
NULL
));
cl_git_pass
(
git_rebase_abort
(
rebase
));
ensure_aborted
(
branch
,
onto
);
git_rebase_free
(
rebase
);
}
...
...
@@ -86,6 +96,32 @@ void test_rebase_abort__merge(void)
git_rebase_free
(
rebase
);
}
void
test_rebase_abort__merge_immediately_after_init
(
void
)
{
git_rebase
*
rebase
;
git_reference
*
branch_ref
,
*
onto_ref
;
git_annotated_commit
*
branch_head
,
*
onto_head
;
cl_git_pass
(
git_reference_lookup
(
&
branch_ref
,
repo
,
"refs/heads/beef"
));
cl_git_pass
(
git_reference_lookup
(
&
onto_ref
,
repo
,
"refs/heads/master"
));
cl_git_pass
(
git_annotated_commit_from_ref
(
&
branch_head
,
repo
,
branch_ref
));
cl_git_pass
(
git_annotated_commit_from_ref
(
&
onto_head
,
repo
,
onto_ref
));
cl_git_pass
(
git_rebase_init
(
&
rebase
,
repo
,
branch_head
,
NULL
,
onto_head
,
NULL
));
cl_assert_equal_i
(
GIT_REPOSITORY_STATE_REBASE_MERGE
,
git_repository_state
(
repo
));
cl_git_pass
(
git_rebase_abort
(
rebase
));
ensure_aborted
(
branch_head
,
onto_head
);
git_annotated_commit_free
(
branch_head
);
git_annotated_commit_free
(
onto_head
);
git_reference_free
(
branch_ref
);
git_reference_free
(
onto_ref
);
git_rebase_free
(
rebase
);
}
void
test_rebase_abort__merge_by_id
(
void
)
{
git_rebase
*
rebase
;
...
...
@@ -109,6 +145,30 @@ void test_rebase_abort__merge_by_id(void)
git_rebase_free
(
rebase
);
}
void
test_rebase_abort__merge_by_id_immediately_after_init
(
void
)
{
git_rebase
*
rebase
;
git_oid
branch_id
,
onto_id
;
git_annotated_commit
*
branch_head
,
*
onto_head
;
cl_git_pass
(
git_oid_fromstr
(
&
branch_id
,
"b146bd7608eac53d9bf9e1a6963543588b555c64"
));
cl_git_pass
(
git_oid_fromstr
(
&
onto_id
,
"efad0b11c47cb2f0220cbd6f5b0f93bb99064b00"
));
cl_git_pass
(
git_annotated_commit_lookup
(
&
branch_head
,
repo
,
&
branch_id
));
cl_git_pass
(
git_annotated_commit_lookup
(
&
onto_head
,
repo
,
&
onto_id
));
cl_git_pass
(
git_rebase_init
(
&
rebase
,
repo
,
branch_head
,
NULL
,
onto_head
,
NULL
));
cl_assert_equal_i
(
GIT_REPOSITORY_STATE_REBASE_MERGE
,
git_repository_state
(
repo
));
cl_git_pass
(
git_rebase_abort
(
rebase
));
ensure_aborted
(
branch_head
,
onto_head
);
git_annotated_commit_free
(
branch_head
);
git_annotated_commit_free
(
onto_head
);
git_rebase_free
(
rebase
);
}
void
test_rebase_abort__detached_head
(
void
)
{
git_rebase
*
rebase
;
...
...
tests/rebase/merge.c
View file @
c30955e0
...
...
@@ -475,6 +475,56 @@ void test_rebase_merge__finish(void)
git_rebase_free
(
rebase
);
}
void
test_rebase_merge__finish_with_ids
(
void
)
{
git_rebase
*
rebase
;
git_reference
*
head_ref
;
git_oid
branch_id
,
upstream_id
;
git_annotated_commit
*
branch_head
,
*
upstream_head
;
git_rebase_operation
*
rebase_operation
;
git_oid
commit_id
;
git_reflog
*
reflog
;
const
git_reflog_entry
*
reflog_entry
;
int
error
;
cl_git_pass
(
git_oid_fromstr
(
&
branch_id
,
"d616d97082eb7bb2dc6f180a7cca940993b7a56f"
));
cl_git_pass
(
git_oid_fromstr
(
&
upstream_id
,
"f87d14a4a236582a0278a916340a793714256864"
));
cl_git_pass
(
git_annotated_commit_lookup
(
&
branch_head
,
repo
,
&
branch_id
));
cl_git_pass
(
git_annotated_commit_lookup
(
&
upstream_head
,
repo
,
&
upstream_id
));
cl_git_pass
(
git_rebase_init
(
&
rebase
,
repo
,
branch_head
,
upstream_head
,
NULL
,
NULL
));
cl_git_pass
(
git_rebase_next
(
&
rebase_operation
,
rebase
));
cl_git_pass
(
git_rebase_commit
(
&
commit_id
,
rebase
,
NULL
,
signature
,
NULL
,
NULL
));
cl_git_fail
(
error
=
git_rebase_next
(
&
rebase_operation
,
rebase
));
cl_assert_equal_i
(
GIT_ITEROVER
,
error
);
cl_git_pass
(
git_rebase_finish
(
rebase
,
signature
));
cl_assert_equal_i
(
GIT_REPOSITORY_STATE_NONE
,
git_repository_state
(
repo
));
cl_git_pass
(
git_reference_lookup
(
&
head_ref
,
repo
,
"HEAD"
));
cl_assert_equal_i
(
GIT_REF_OID
,
git_reference_type
(
head_ref
));
cl_assert_equal_oid
(
&
commit_id
,
git_reference_target
(
head_ref
));
/* reflogs are not updated as if we were operating on proper
* branches. check that the last reflog entry is the rebase.
*/
cl_git_pass
(
git_reflog_read
(
&
reflog
,
repo
,
"HEAD"
));
cl_assert
(
reflog_entry
=
git_reflog_entry_byindex
(
reflog
,
0
));
cl_assert_equal_oid
(
&
commit_id
,
git_reflog_entry_id_new
(
reflog_entry
));
cl_assert_equal_s
(
"rebase: Modification 3 to gravy"
,
git_reflog_entry_message
(
reflog_entry
));
git_reflog_free
(
reflog
);
git_annotated_commit_free
(
branch_head
);
git_annotated_commit_free
(
upstream_head
);
git_reference_free
(
head_ref
);
git_rebase_free
(
rebase
);
}
static
void
test_copy_note
(
const
git_rebase_options
*
opts
,
bool
should_exist
)
...
...
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