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
7376ad99
Commit
7376ad99
authored
Jun 29, 2011
by
Vicent Marti
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
refs: Remove duplicate rename method
`git_reference_rename` now takes a `force` flag
parent
5f25149e
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
140 additions
and
164 deletions
+140
-164
include/git2/refs.h
+1
-15
src/refs.c
+132
-142
tests/t10-refs.c
+7
-7
No files found.
include/git2/refs.h
View file @
7376ad99
...
...
@@ -195,21 +195,7 @@ GIT_EXTERN(int) git_reference_set_oid(git_reference *ref, const git_oid *id);
* and on disk.
*
*/
GIT_EXTERN
(
int
)
git_reference_rename
(
git_reference
*
ref
,
const
char
*
new_name
);
/**
* Rename an existing reference, overwriting an existing one with the
* same name, if it exists.
*
* This method works for both direct and symbolic references.
* The new name will be checked for validity and may be
* modified into a normalized form.
*
* The refernece will be immediately renamed in-memory
* and on disk.
*
*/
GIT_EXTERN
(
int
)
git_reference_rename_f
(
git_reference
*
ref
,
const
char
*
new_name
);
GIT_EXTERN
(
int
)
git_reference_rename
(
git_reference
*
ref
,
const
char
*
new_name
,
int
force
);
/**
* Delete an existing reference
...
...
src/refs.c
View file @
7376ad99
...
...
@@ -80,7 +80,6 @@ static int packed_sort(const void *a, const void *b);
static
int
packed_write
(
git_repository
*
repo
);
/* internal helpers */
static
int
reference_rename
(
git_reference
*
ref
,
const
char
*
new_name
,
int
force
);
static
int
reference_available
(
git_repository
*
repo
,
const
char
*
ref
,
const
char
*
old_ref
);
/* name normalization */
...
...
@@ -962,137 +961,6 @@ static int reference_available(git_repository *repo, const char *ref, const char
return
error
==
GIT_SUCCESS
?
GIT_SUCCESS
:
git__throw
(
GIT_EEXISTS
,
"Reference name `%s` conflicts with existing reference"
,
ref
);
}
/*
* Rename a reference
*
* If the reference is packed, we need to rewrite the
* packfile to remove the reference from it and create
* the reference back as a loose one.
*
* If the reference is loose, we just rename it on
* the filesystem.
*
* We also need to re-insert the reference on its corresponding
* in-memory cache, since the caches are indexed by refname.
*/
static
int
reference_rename
(
git_reference
*
ref
,
const
char
*
new_name
,
int
force
)
{
int
error
;
char
*
old_name
;
char
old_path
[
GIT_PATH_MAX
],
new_path
[
GIT_PATH_MAX
],
normalized_name
[
GIT_REFNAME_MAX
];
git_reference
*
looked_up_ref
,
*
old_ref
=
NULL
;
assert
(
ref
);
/* Ensure the name is valid */
error
=
normalize_name
(
normalized_name
,
sizeof
(
normalized_name
),
new_name
,
ref
->
type
&
GIT_REF_OID
);
if
(
error
<
GIT_SUCCESS
)
return
git__rethrow
(
error
,
"Failed to rename reference"
);
new_name
=
normalized_name
;
/* Ensure we're not going to overwrite an existing reference
unless the user has allowed us */
error
=
git_reference_lookup
(
&
looked_up_ref
,
ref
->
owner
,
new_name
);
if
(
error
==
GIT_SUCCESS
&&
!
force
)
return
git__throw
(
GIT_EEXISTS
,
"Failed to rename reference. Reference already exists"
);
if
(
error
<
GIT_SUCCESS
&&
error
!=
GIT_ENOTFOUND
)
return
git__rethrow
(
error
,
"Failed to rename reference"
);
if
((
error
=
reference_available
(
ref
->
owner
,
new_name
,
ref
->
name
))
<
GIT_SUCCESS
)
return
error
==
GIT_SUCCESS
?
GIT_SUCCESS
:
git__rethrow
(
error
,
"Failed to rename reference. Reference already exists"
);
old_name
=
ref
->
name
;
ref
->
name
=
git__strdup
(
new_name
);
if
(
ref
->
name
==
NULL
)
{
ref
->
name
=
old_name
;
return
GIT_ENOMEM
;
}
if
(
ref
->
type
&
GIT_REF_PACKED
)
{
/* write the packfile to disk; note
* that the state of the in-memory cache is not
* consistent, because the reference is indexed
* by its old name but it already has the new one.
* This doesn't affect writing, though, and allows
* us to rollback if writing fails
*/
ref
->
type
&=
~
GIT_REF_PACKED
;
/* Create the loose ref under its new name */
error
=
loose_write
(
ref
);
if
(
error
<
GIT_SUCCESS
)
{
ref
->
type
|=
GIT_REF_PACKED
;
goto
cleanup
;
}
/* Remove from the packfile cache in order to avoid packing it back
* Note : we do not rely on git_reference_delete() because this would
* invalidate the reference.
*/
git_hashtable_remove
(
ref
->
owner
->
references
.
packfile
,
old_name
);
/* Recreate the packed-refs file without the reference */
error
=
packed_write
(
ref
->
owner
);
if
(
error
<
GIT_SUCCESS
)
goto
rename_loose_to_old_name
;
}
else
{
git__joinpath
(
old_path
,
ref
->
owner
->
path_repository
,
old_name
);
git__joinpath
(
new_path
,
ref
->
owner
->
path_repository
,
ref
->
name
);
error
=
gitfo_mv_force
(
old_path
,
new_path
);
if
(
error
<
GIT_SUCCESS
)
goto
cleanup
;
/* Once succesfully renamed, remove from the cache the reference known by its old name*/
git_hashtable_remove
(
ref
->
owner
->
references
.
loose_cache
,
old_name
);
}
/* Store the renamed reference into the loose ref cache */
error
=
git_hashtable_insert2
(
ref
->
owner
->
references
.
loose_cache
,
ref
->
name
,
ref
,
(
void
**
)
&
old_ref
);
/* If we force-replaced, we need to free the old reference */
if
(
old_ref
)
reference_free
(
old_ref
);
free
(
old_name
);
return
error
==
GIT_SUCCESS
?
GIT_SUCCESS
:
git__rethrow
(
error
,
"Failed to rename reference"
);
cleanup:
/* restore the old name if this failed */
free
(
ref
->
name
);
ref
->
name
=
old_name
;
return
error
==
GIT_SUCCESS
?
GIT_SUCCESS
:
git__rethrow
(
error
,
"Failed to rename reference"
);
rename_loose_to_old_name:
/* If we hit this point. Something *bad* happened! Think "Ghostbusters
* crossing the streams" definition of bad.
* Either the packed-refs has been correctly generated and something else
* has gone wrong, or the writing of the new packed-refs has failed, and
* we're stuck with the old one. As a loose ref always takes priority over
* a packed ref, we'll eventually try and rename the generated loose ref to
* its former name. It even that fails, well... we might have lost the reference
* for good. :-/
*/
git__joinpath
(
old_path
,
ref
->
owner
->
path_repository
,
ref
->
name
);
git__joinpath
(
new_path
,
ref
->
owner
->
path_repository
,
old_name
);
/* No error checking. We'll return the initial error */
gitfo_mv_force
(
old_path
,
new_path
);
/* restore the old name */
free
(
ref
->
name
);
ref
->
name
=
old_name
;
return
error
==
GIT_SUCCESS
?
GIT_SUCCESS
:
git__rethrow
(
error
,
"Failed to rename reference"
);
}
/*****************************************
* External Library API
*****************************************/
...
...
@@ -1422,6 +1290,138 @@ int git_reference_set_target(git_reference *ref, const char *target)
*/
/*
* Rename a reference
*
* If the reference is packed, we need to rewrite the
* packfile to remove the reference from it and create
* the reference back as a loose one.
*
* If the reference is loose, we just rename it on
* the filesystem.
*
* We also need to re-insert the reference on its corresponding
* in-memory cache, since the caches are indexed by refname.
*/
int
git_reference_rename
(
git_reference
*
ref
,
const
char
*
new_name
,
int
force
)
{
int
error
;
char
*
old_name
;
char
old_path
[
GIT_PATH_MAX
],
new_path
[
GIT_PATH_MAX
],
normalized_name
[
GIT_REFNAME_MAX
];
git_reference
*
looked_up_ref
,
*
old_ref
=
NULL
;
assert
(
ref
);
/* Ensure the name is valid */
error
=
normalize_name
(
normalized_name
,
sizeof
(
normalized_name
),
new_name
,
ref
->
type
&
GIT_REF_OID
);
if
(
error
<
GIT_SUCCESS
)
return
git__rethrow
(
error
,
"Failed to rename reference"
);
new_name
=
normalized_name
;
/* Ensure we're not going to overwrite an existing reference
unless the user has allowed us */
error
=
git_reference_lookup
(
&
looked_up_ref
,
ref
->
owner
,
new_name
);
if
(
error
==
GIT_SUCCESS
&&
!
force
)
return
git__throw
(
GIT_EEXISTS
,
"Failed to rename reference. Reference already exists"
);
if
(
error
<
GIT_SUCCESS
&&
error
!=
GIT_ENOTFOUND
)
return
git__rethrow
(
error
,
"Failed to rename reference"
);
if
((
error
=
reference_available
(
ref
->
owner
,
new_name
,
ref
->
name
))
<
GIT_SUCCESS
)
return
error
==
GIT_SUCCESS
?
GIT_SUCCESS
:
git__rethrow
(
error
,
"Failed to rename reference. Reference already exists"
);
old_name
=
ref
->
name
;
ref
->
name
=
git__strdup
(
new_name
);
if
(
ref
->
name
==
NULL
)
{
ref
->
name
=
old_name
;
return
GIT_ENOMEM
;
}
if
(
ref
->
type
&
GIT_REF_PACKED
)
{
/* write the packfile to disk; note
* that the state of the in-memory cache is not
* consistent, because the reference is indexed
* by its old name but it already has the new one.
* This doesn't affect writing, though, and allows
* us to rollback if writing fails
*/
ref
->
type
&=
~
GIT_REF_PACKED
;
/* Create the loose ref under its new name */
error
=
loose_write
(
ref
);
if
(
error
<
GIT_SUCCESS
)
{
ref
->
type
|=
GIT_REF_PACKED
;
goto
cleanup
;
}
/* Remove from the packfile cache in order to avoid packing it back
* Note : we do not rely on git_reference_delete() because this would
* invalidate the reference.
*/
git_hashtable_remove
(
ref
->
owner
->
references
.
packfile
,
old_name
);
/* Recreate the packed-refs file without the reference */
error
=
packed_write
(
ref
->
owner
);
if
(
error
<
GIT_SUCCESS
)
goto
rename_loose_to_old_name
;
}
else
{
git__joinpath
(
old_path
,
ref
->
owner
->
path_repository
,
old_name
);
git__joinpath
(
new_path
,
ref
->
owner
->
path_repository
,
ref
->
name
);
error
=
gitfo_mv_force
(
old_path
,
new_path
);
if
(
error
<
GIT_SUCCESS
)
goto
cleanup
;
/* Once succesfully renamed, remove from the cache the reference known by its old name*/
git_hashtable_remove
(
ref
->
owner
->
references
.
loose_cache
,
old_name
);
}
/* Store the renamed reference into the loose ref cache */
error
=
git_hashtable_insert2
(
ref
->
owner
->
references
.
loose_cache
,
ref
->
name
,
ref
,
(
void
**
)
&
old_ref
);
/* If we force-replaced, we need to free the old reference */
if
(
old_ref
)
reference_free
(
old_ref
);
free
(
old_name
);
return
error
==
GIT_SUCCESS
?
GIT_SUCCESS
:
git__rethrow
(
error
,
"Failed to rename reference"
);
cleanup:
/* restore the old name if this failed */
free
(
ref
->
name
);
ref
->
name
=
old_name
;
return
error
==
GIT_SUCCESS
?
GIT_SUCCESS
:
git__rethrow
(
error
,
"Failed to rename reference"
);
rename_loose_to_old_name:
/* If we hit this point. Something *bad* happened! Think "Ghostbusters
* crossing the streams" definition of bad.
* Either the packed-refs has been correctly generated and something else
* has gone wrong, or the writing of the new packed-refs has failed, and
* we're stuck with the old one. As a loose ref always takes priority over
* a packed ref, we'll eventually try and rename the generated loose ref to
* its former name. It even that fails, well... we might have lost the reference
* for good. :-/
*/
git__joinpath
(
old_path
,
ref
->
owner
->
path_repository
,
ref
->
name
);
git__joinpath
(
new_path
,
ref
->
owner
->
path_repository
,
old_name
);
/* No error checking. We'll return the initial error */
gitfo_mv_force
(
old_path
,
new_path
);
/* restore the old name */
free
(
ref
->
name
);
ref
->
name
=
old_name
;
return
error
==
GIT_SUCCESS
?
GIT_SUCCESS
:
git__rethrow
(
error
,
"Failed to rename reference"
);
}
/*
* Delete a reference.
*
* If the reference is packed, this is an expensive
...
...
@@ -1474,16 +1474,6 @@ cleanup:
return
error
==
GIT_SUCCESS
?
GIT_SUCCESS
:
git__rethrow
(
error
,
"Failed to delete reference"
);
}
int
git_reference_rename
(
git_reference
*
ref
,
const
char
*
new_name
)
{
return
reference_rename
(
ref
,
new_name
,
0
);
}
int
git_reference_rename_f
(
git_reference
*
ref
,
const
char
*
new_name
)
{
return
reference_rename
(
ref
,
new_name
,
1
);
}
int
git_reference_resolve
(
git_reference
**
resolved_ref
,
git_reference
*
ref
)
{
git_repository
*
repo
;
...
...
tests/t10-refs.c
View file @
7376ad99
...
...
@@ -494,7 +494,7 @@ BEGIN_TEST(rename0, "rename a loose reference")
must_be_true
((
looked_up_ref
->
type
&
GIT_REF_PACKED
)
==
0
);
/* Now that the reference is renamed... */
must_pass
(
git_reference_rename
(
looked_up_ref
,
new_name
));
must_pass
(
git_reference_rename
(
looked_up_ref
,
new_name
,
0
));
must_be_true
(
!
strcmp
(
looked_up_ref
->
name
,
new_name
));
/* ...It can't be looked-up with the old name... */
...
...
@@ -534,7 +534,7 @@ BEGIN_TEST(rename1, "rename a packed reference (should make it loose)")
must_be_true
((
looked_up_ref
->
type
&
GIT_REF_PACKED
)
!=
0
);
/* Now that the reference is renamed... */
must_pass
(
git_reference_rename
(
looked_up_ref
,
brand_new_name
));
must_pass
(
git_reference_rename
(
looked_up_ref
,
brand_new_name
,
0
));
must_be_true
(
!
strcmp
(
looked_up_ref
->
name
,
brand_new_name
));
/* ...It can't be looked-up with the old name... */
...
...
@@ -580,7 +580,7 @@ BEGIN_TEST(rename2, "renaming a packed reference does not pack another reference
must_be_true
((
looked_up_ref
->
type
&
GIT_REF_PACKED
)
!=
0
);
/* Now that the reference is renamed... */
must_pass
(
git_reference_rename
(
looked_up_ref
,
brand_new_name
));
must_pass
(
git_reference_rename
(
looked_up_ref
,
brand_new_name
,
0
));
/* Lookup the other reference */
must_pass
(
git_reference_lookup
(
&
another_looked_up_ref
,
repo
,
packed_test_head_name
));
...
...
@@ -604,7 +604,7 @@ BEGIN_TEST(rename3, "can not rename a reference with the name of an existing ref
must_pass
(
git_reference_lookup
(
&
looked_up_ref
,
repo
,
packed_head_name
));
/* Can not be renamed to the name of another existing reference. */
must_fail
(
git_reference_rename
(
looked_up_ref
,
packed_test_head_name
));
must_fail
(
git_reference_rename
(
looked_up_ref
,
packed_test_head_name
,
0
));
/* Failure to rename it hasn't corrupted its state */
must_pass
(
git_reference_lookup
(
&
looked_up_ref
,
repo
,
packed_head_name
));
...
...
@@ -623,10 +623,10 @@ BEGIN_TEST(rename4, "can not rename a reference with an invalid name")
must_pass
(
git_reference_lookup
(
&
looked_up_ref
,
repo
,
packed_test_head_name
));
/* Can not be renamed with an invalid name. */
must_fail
(
git_reference_rename
(
looked_up_ref
,
"Hello! I'm a very invalid name."
));
must_fail
(
git_reference_rename
(
looked_up_ref
,
"Hello! I'm a very invalid name."
,
0
));
/* Can not be renamed outside of the refs hierarchy. */
must_fail
(
git_reference_rename
(
looked_up_ref
,
"i-will-sudo-you"
));
must_fail
(
git_reference_rename
(
looked_up_ref
,
"i-will-sudo-you"
,
0
));
/* Failure to rename it hasn't corrupted its state */
must_pass
(
git_reference_lookup
(
&
looked_up_ref
,
repo
,
packed_test_head_name
));
...
...
@@ -645,7 +645,7 @@ BEGIN_TEST(rename5, "can force-rename a reference with the name of an existing r
must_pass
(
git_reference_lookup
(
&
looked_up_ref
,
repo
,
packed_head_name
));
/* Can be force-renamed to the name of another existing reference. */
must_pass
(
git_reference_rename
_f
(
looked_up_ref
,
packed_test_head_name
));
must_pass
(
git_reference_rename
(
looked_up_ref
,
packed_test_head_name
,
1
));
/* Check we actually renamed it */
must_pass
(
git_reference_lookup
(
&
looked_up_ref
,
repo
,
packed_test_head_name
));
...
...
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