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
228272ef
Commit
228272ef
authored
May 16, 2014
by
Vicent Marti
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #2313 from libgit2/cmn/remote-delete
Remote deletion
parents
8e1b5a8d
ec8a949a
Show whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
250 additions
and
2 deletions
+250
-2
include/git2/remote.h
+13
-0
src/remote.c
+144
-2
tests/config/config_helpers.c
+28
-0
tests/config/config_helpers.h
+4
-0
tests/network/remote/delete.c
+61
-0
No files found.
include/git2/remote.h
View file @
228272ef
...
...
@@ -610,6 +610,19 @@ GIT_EXTERN(void) git_remote_set_update_fetchhead(git_remote *remote, int value);
*/
GIT_EXTERN
(
int
)
git_remote_is_valid_name
(
const
char
*
remote_name
);
/**
* Delete an existing persisted remote.
*
* All remote-tracking branches and configuration settings
* for the remote will be removed.
*
* once deleted, the passed remote object will be freed and invalidated.
*
* @param remote A valid remote
* @return 0 on success, or an error code.
*/
GIT_EXTERN
(
int
)
git_remote_delete
(
git_remote
*
remote
);
/** @} */
GIT_END_DECL
#endif
src/remote.c
View file @
228272ef
...
...
@@ -1304,13 +1304,14 @@ static int rename_remote_config_section(
if
(
git_buf_printf
(
&
old_section_name
,
"remote.%s"
,
old_name
)
<
0
)
goto
cleanup
;
if
(
git_buf_printf
(
&
new_section_name
,
"remote.%s"
,
new_name
)
<
0
)
if
(
new_name
&&
(
git_buf_printf
(
&
new_section_name
,
"remote.%s"
,
new_name
)
<
0
))
goto
cleanup
;
error
=
git_config_rename_section
(
repo
,
git_buf_cstr
(
&
old_section_name
),
git_buf_cstr
(
&
new_section_name
)
);
new_name
?
git_buf_cstr
(
&
new_section_name
)
:
NULL
);
cleanup:
git_buf_free
(
&
old_section_name
);
...
...
@@ -1743,3 +1744,144 @@ int git_remote_init_callbacks(git_remote_callbacks *opts, unsigned int version)
opts
,
version
,
git_remote_callbacks
,
GIT_REMOTE_CALLBACKS_INIT
);
return
0
;
}
/* asserts a branch.<foo>.remote format */
static
const
char
*
name_offset
(
size_t
*
len_out
,
const
char
*
name
)
{
size_t
prefix_len
;
const
char
*
dot
;
prefix_len
=
strlen
(
"remote."
);
dot
=
strchr
(
name
+
prefix_len
,
'.'
);
assert
(
dot
);
*
len_out
=
dot
-
name
-
prefix_len
;
return
name
+
prefix_len
;
}
static
int
remove_branch_config_related_entries
(
git_repository
*
repo
,
const
char
*
remote_name
)
{
int
error
;
git_config
*
config
;
git_config_entry
*
entry
;
git_config_iterator
*
iter
;
git_buf
buf
=
GIT_BUF_INIT
;
if
((
error
=
git_repository_config__weakptr
(
&
config
,
repo
))
<
0
)
return
error
;
if
((
error
=
git_config_iterator_glob_new
(
&
iter
,
config
,
"branch
\\
..+
\\
.remote"
))
<
0
)
return
error
;
/* find any branches with us as upstream and remove that config */
while
((
error
=
git_config_next
(
&
entry
,
iter
))
==
0
)
{
const
char
*
branch
;
size_t
branch_len
;
if
(
strcmp
(
remote_name
,
entry
->
value
))
continue
;
branch
=
name_offset
(
&
branch_len
,
entry
->
name
);
git_buf_clear
(
&
buf
);
if
(
git_buf_printf
(
&
buf
,
"branch.%.*s.merge"
,
(
int
)
branch_len
,
branch
)
<
0
)
break
;
if
((
error
=
git_config_delete_entry
(
config
,
git_buf_cstr
(
&
buf
)))
<
0
)
break
;
git_buf_clear
(
&
buf
);
if
(
git_buf_printf
(
&
buf
,
"branch.%.*s.remote"
,
(
int
)
branch_len
,
branch
)
<
0
)
break
;
if
((
error
=
git_config_delete_entry
(
config
,
git_buf_cstr
(
&
buf
)))
<
0
)
break
;
}
if
(
error
==
GIT_ITEROVER
)
error
=
0
;
git_buf_free
(
&
buf
);
git_config_iterator_free
(
iter
);
return
error
;
}
static
int
remove_refs
(
git_repository
*
repo
,
const
char
*
glob
)
{
git_reference_iterator
*
iter
;
const
char
*
name
;
int
error
;
if
((
error
=
git_reference_iterator_glob_new
(
&
iter
,
repo
,
glob
))
<
0
)
return
error
;
while
((
error
=
git_reference_next_name
(
&
name
,
iter
))
==
0
)
{
if
((
error
=
git_reference_remove
(
repo
,
name
))
<
0
)
break
;
}
git_reference_iterator_free
(
iter
);
if
(
error
==
GIT_ITEROVER
)
error
=
0
;
return
error
;
}
static
int
remove_remote_tracking
(
git_repository
*
repo
,
const
char
*
remote_name
)
{
git_remote
*
remote
;
int
error
;
size_t
i
,
count
;
/* we want to use what's on the config, regardless of changes to the instance in memory */
if
((
error
=
git_remote_load
(
&
remote
,
repo
,
remote_name
))
<
0
)
return
error
;
count
=
git_remote_refspec_count
(
remote
);
for
(
i
=
0
;
i
<
count
;
i
++
)
{
const
git_refspec
*
refspec
=
git_remote_get_refspec
(
remote
,
i
);
/* shouldn't ever actually happen */
if
(
refspec
==
NULL
)
continue
;
if
((
error
=
remove_refs
(
repo
,
git_refspec_dst
(
refspec
)))
<
0
)
break
;
}
git_remote_free
(
remote
);
return
error
;
}
int
git_remote_delete
(
git_remote
*
remote
)
{
int
error
;
git_repository
*
repo
;
assert
(
remote
);
if
(
!
remote
->
name
)
{
giterr_set
(
GITERR_INVALID
,
"Can't delete an anonymous remote."
);
return
-
1
;
}
repo
=
git_remote_owner
(
remote
);
if
((
error
=
remove_branch_config_related_entries
(
repo
,
git_remote_name
(
remote
)))
<
0
)
return
error
;
if
((
error
=
remove_remote_tracking
(
repo
,
git_remote_name
(
remote
)))
<
0
)
return
error
;
if
((
error
=
rename_remote_config_section
(
repo
,
git_remote_name
(
remote
),
NULL
))
<
0
)
return
error
;
git_remote_free
(
remote
);
return
0
;
}
tests/config/config_helpers.c
View file @
228272ef
...
...
@@ -35,3 +35,31 @@ void assert_config_entry_value(
cl_assert_equal_s
(
expected_value
,
out
);
}
static
int
count_config_entries_cb
(
const
git_config_entry
*
entry
,
void
*
payload
)
{
int
*
how_many
=
(
int
*
)
payload
;
GIT_UNUSED
(
entry
);
(
*
how_many
)
++
;
return
0
;
}
int
count_config_entries_match
(
git_repository
*
repo
,
const
char
*
pattern
)
{
git_config
*
config
;
int
how_many
=
0
;
cl_git_pass
(
git_repository_config
(
&
config
,
repo
));
cl_assert_equal_i
(
0
,
git_config_foreach_match
(
config
,
pattern
,
count_config_entries_cb
,
&
how_many
));
git_config_free
(
config
);
return
how_many
;
}
tests/config/config_helpers.h
View file @
228272ef
...
...
@@ -7,3 +7,7 @@ extern void assert_config_entry_value(
git_repository
*
repo
,
const
char
*
name
,
const
char
*
expected_value
);
extern
int
count_config_entries_match
(
git_repository
*
repo
,
const
char
*
pattern
);
tests/network/remote/delete.c
0 → 100644
View file @
228272ef
#include "clar_libgit2.h"
#include "config/config_helpers.h"
#include "repository.h"
static
git_remote
*
_remote
;
static
git_repository
*
_repo
;
void
test_network_remote_delete__initialize
(
void
)
{
_repo
=
cl_git_sandbox_init
(
"testrepo.git"
);
cl_git_pass
(
git_remote_load
(
&
_remote
,
_repo
,
"test"
));
}
void
test_network_remote_delete__cleanup
(
void
)
{
cl_git_sandbox_cleanup
();
}
void
test_network_remote_delete__cannot_delete_an_anonymous_remote
(
void
)
{
git_remote
*
remote
;
cl_git_pass
(
git_remote_create_anonymous
(
&
remote
,
_repo
,
"git://github.com/libgit2/libgit2"
,
NULL
));
cl_git_fail
(
git_remote_delete
(
remote
));
git_remote_free
(
remote
);
git_remote_free
(
_remote
);
}
void
test_network_remote_delete__remove_remote_tracking_branches
(
void
)
{
git_reference
*
ref
;
cl_git_pass
(
git_remote_delete
(
_remote
));
cl_git_fail_with
(
GIT_ENOTFOUND
,
git_reference_lookup
(
&
ref
,
_repo
,
"refs/remotes/test/master"
));
}
void
test_network_remote_delete__remove_remote_configuration_settings
(
void
)
{
cl_assert
(
count_config_entries_match
(
_repo
,
"remote
\\
.test
\\
.+"
)
>
0
);
cl_git_pass
(
git_remote_delete
(
_remote
));
cl_assert_equal_i
(
0
,
count_config_entries_match
(
_repo
,
"remote
\\
.test
\\
.+"
));
}
void
test_network_remote_delete__remove_branch_upstream_configuration_settings
(
void
)
{
assert_config_entry_existence
(
_repo
,
"branch.mergeless.remote"
,
true
);
assert_config_entry_existence
(
_repo
,
"branch.master.remote"
,
true
);
cl_git_pass
(
git_remote_delete
(
_remote
));
assert_config_entry_existence
(
_repo
,
"branch.mergeless.remote"
,
false
);
assert_config_entry_existence
(
_repo
,
"branch.mergeless.merge"
,
false
);
assert_config_entry_existence
(
_repo
,
"branch.master.remote"
,
false
);
assert_config_entry_existence
(
_repo
,
"branch.master.merge"
,
false
);
}
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