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
9 years ago
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
);
...
...
This diff is collapsed.
Click to expand it.
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
;
...
...
This diff is collapsed.
Click to expand it.
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
)
...
...
This diff is collapsed.
Click to expand it.
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