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
3a72345b
Unverified
Commit
3a72345b
authored
Oct 04, 2020
by
Edward Thomson
Committed by
GitHub
Oct 04, 2020
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #5581 from libgit2/ethomson/mainbranch
Respect `init.defaultBranch` setting
parents
a94fedc1
0ff70f4a
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
181 additions
and
46 deletions
+181
-46
src/clone.c
+30
-6
src/refs.h
+0
-1
src/remote.c
+27
-14
src/repository.c
+85
-25
src/repository.h
+6
-0
tests/clone/empty.c
+17
-0
tests/repo/init.c
+16
-0
No files found.
src/clone.c
View file @
3a72345b
...
...
@@ -137,6 +137,31 @@ static int update_head_to_new_branch(
return
error
;
}
static
int
update_head_to_default
(
git_repository
*
repo
)
{
git_buf
initialbranch
=
GIT_BUF_INIT
;
const
char
*
branch_name
;
int
error
=
0
;
if
((
error
=
git_repository_initialbranch
(
&
initialbranch
,
repo
))
<
0
)
goto
done
;
if
(
git__prefixcmp
(
initialbranch
.
ptr
,
GIT_REFS_HEADS_DIR
)
!=
0
)
{
git_error_set
(
GIT_ERROR_INVALID
,
"invalid initial branch '%s'"
,
initialbranch
.
ptr
);
error
=
-
1
;
goto
done
;
}
branch_name
=
initialbranch
.
ptr
+
strlen
(
GIT_REFS_HEADS_DIR
);
error
=
setup_tracking_config
(
repo
,
branch_name
,
GIT_REMOTE_ORIGIN
,
initialbranch
.
ptr
);
done:
git_buf_dispose
(
&
initialbranch
);
return
error
;
}
static
int
update_head_to_remote
(
git_repository
*
repo
,
git_remote
*
remote
,
...
...
@@ -147,7 +172,7 @@ static int update_head_to_remote(
git_refspec
*
refspec
;
const
git_remote_head
*
remote_head
,
**
refs
;
const
git_oid
*
remote_head_id
;
git_buf
remote_
master
_name
=
GIT_BUF_INIT
;
git_buf
remote_
branch
_name
=
GIT_BUF_INIT
;
git_buf
branch
=
GIT_BUF_INIT
;
if
((
error
=
git_remote_ls
(
&
refs
,
&
refs_len
,
remote
))
<
0
)
...
...
@@ -155,8 +180,7 @@ static int update_head_to_remote(
/* We cloned an empty repository or one with an unborn HEAD */
if
(
refs_len
==
0
||
strcmp
(
refs
[
0
]
->
name
,
GIT_HEAD_FILE
))
return
setup_tracking_config
(
repo
,
"master"
,
GIT_REMOTE_ORIGIN
,
GIT_REFS_HEADS_MASTER_FILE
);
return
update_head_to_default
(
repo
);
/* We know we have HEAD, let's see where it points */
remote_head
=
refs
[
0
];
...
...
@@ -179,9 +203,9 @@ static int update_head_to_remote(
goto
cleanup
;
}
/* Determine the remote tracking ref
erence name from the local master
*/
/* Determine the remote tracking ref
name from the local branch
*/
if
((
error
=
git_refspec_transform
(
&
remote_
master
_name
,
&
remote_
branch
_name
,
refspec
,
git_buf_cstr
(
&
branch
)))
<
0
)
goto
cleanup
;
...
...
@@ -193,7 +217,7 @@ static int update_head_to_remote(
reflog_message
);
cleanup:
git_buf_dispose
(
&
remote_
master
_name
);
git_buf_dispose
(
&
remote_
branch
_name
);
git_buf_dispose
(
&
branch
);
return
error
;
...
...
src/refs.h
View file @
3a72345b
...
...
@@ -45,7 +45,6 @@ extern bool git_reference__enable_symbolic_ref_target_validation;
#define GIT_REBASE_APPLY_DIR "rebase-apply/"
#define GIT_REBASE_APPLY_REBASING_FILE GIT_REBASE_APPLY_DIR "rebasing"
#define GIT_REBASE_APPLY_APPLYING_FILE GIT_REBASE_APPLY_DIR "applying"
#define GIT_REFS_HEADS_MASTER_FILE GIT_REFS_HEADS_DIR "master"
#define GIT_SEQUENCER_DIR "sequencer/"
#define GIT_SEQUENCER_HEAD_FILE GIT_SEQUENCER_DIR "head"
...
...
src/remote.c
View file @
3a72345b
...
...
@@ -2375,29 +2375,36 @@ int git_remote_default_branch(git_buf *out, git_remote *remote)
const
git_remote_head
*
guess
=
NULL
;
const
git_oid
*
head_id
;
size_t
heads_len
,
i
;
git_buf
local_default
=
GIT_BUF_INIT
;
int
error
;
assert
(
out
);
if
((
error
=
git_remote_ls
(
&
heads
,
&
heads_len
,
remote
))
<
0
)
return
error
;
if
(
heads_len
==
0
)
return
GIT_ENOTFOUND
;
goto
done
;
if
(
strcmp
(
heads
[
0
]
->
name
,
GIT_HEAD_FILE
))
return
GIT_ENOTFOUND
;
if
(
heads_len
==
0
||
strcmp
(
heads
[
0
]
->
name
,
GIT_HEAD_FILE
))
{
error
=
GIT_ENOTFOUND
;
goto
done
;
}
git_buf_sanitize
(
out
);
/* the first one must be HEAD so if that has the symref info, we're done */
if
(
heads
[
0
]
->
symref_target
)
return
git_buf_puts
(
out
,
heads
[
0
]
->
symref_target
);
if
(
heads
[
0
]
->
symref_target
)
{
error
=
git_buf_puts
(
out
,
heads
[
0
]
->
symref_target
);
goto
done
;
}
/*
* If there's no symref information, we have to look over them
* and guess. We return the first match unless the
master
* branch is a candidate. Then we return the
master
branch.
* and guess. We return the first match unless the
default
* branch is a candidate. Then we return the
default
branch.
*/
if
((
error
=
git_repository_initialbranch
(
&
local_default
,
remote
->
repo
))
<
0
)
goto
done
;
head_id
=
&
heads
[
0
]
->
oid
;
for
(
i
=
1
;
i
<
heads_len
;
i
++
)
{
...
...
@@ -2412,16 +2419,22 @@ int git_remote_default_branch(git_buf *out, git_remote *remote)
continue
;
}
if
(
!
git__strcmp
(
GIT_REFS_HEADS_MASTER_FILE
,
heads
[
i
]
->
name
))
{
if
(
!
git__strcmp
(
local_default
.
ptr
,
heads
[
i
]
->
name
))
{
guess
=
heads
[
i
];
break
;
}
}
if
(
!
guess
)
return
GIT_ENOTFOUND
;
if
(
!
guess
)
{
error
=
GIT_ENOTFOUND
;
goto
done
;
}
error
=
git_buf_puts
(
out
,
guess
->
name
);
return
git_buf_puts
(
out
,
guess
->
name
);
done:
git_buf_dispose
(
&
local_default
);
return
error
;
}
int
git_remote_upload
(
git_remote
*
remote
,
const
git_strarray
*
refspecs
,
const
git_push_options
*
opts
)
...
...
src/repository.c
View file @
3a72345b
...
...
@@ -70,7 +70,7 @@ static int check_extensions(git_config *config, int version);
#define GIT_FILE_CONTENT_PREFIX "gitdir:"
#define GIT_BRANCH_
MASTER
"master"
#define GIT_BRANCH_
DEFAULT
"master"
#define GIT_REPO_VERSION 0
#define GIT_REPO_MAX_VERSION 1
...
...
@@ -1408,9 +1408,6 @@ int git_repository_create_head(const char *git_dir, const char *ref_name)
(
error
=
git_filebuf_open
(
&
ref
,
ref_path
.
ptr
,
0
,
GIT_REFS_FILE_MODE
))
<
0
)
goto
out
;
if
(
!
ref_name
)
ref_name
=
GIT_BRANCH_MASTER
;
if
(
git__prefixcmp
(
ref_name
,
GIT_REFS_DIR
)
==
0
)
fmt
=
"ref: %s
\n
"
;
else
...
...
@@ -2061,6 +2058,43 @@ static int repo_init_directories(
return
error
;
}
static
int
repo_init_head
(
const
char
*
repo_dir
,
const
char
*
given
)
{
git_config
*
cfg
=
NULL
;
git_buf
head_path
=
GIT_BUF_INIT
,
cfg_branch
=
GIT_BUF_INIT
;
const
char
*
initial_head
=
NULL
;
int
error
;
if
((
error
=
git_buf_joinpath
(
&
head_path
,
repo_dir
,
GIT_HEAD_FILE
))
<
0
)
goto
out
;
/*
* A template may have set a HEAD; use that unless it's been
* overridden by the caller's given initial head setting.
*/
if
(
git_path_exists
(
head_path
.
ptr
)
&&
!
given
)
goto
out
;
if
(
given
)
{
initial_head
=
given
;
}
else
if
((
error
=
git_config_open_default
(
&
cfg
))
>=
0
&&
(
error
=
git_config_get_string_buf
(
&
cfg_branch
,
cfg
,
"init.defaultbranch"
))
>=
0
)
{
initial_head
=
cfg_branch
.
ptr
;
}
if
(
!
initial_head
)
initial_head
=
GIT_BRANCH_DEFAULT
;
error
=
git_repository_create_head
(
repo_dir
,
initial_head
);
out:
git_config_free
(
cfg
);
git_buf_dispose
(
&
head_path
);
git_buf_dispose
(
&
cfg_branch
);
return
error
;
}
static
int
repo_init_create_origin
(
git_repository
*
repo
,
const
char
*
url
)
{
int
error
;
...
...
@@ -2091,7 +2125,7 @@ int git_repository_init_ext(
git_repository_init_options
*
opts
)
{
git_buf
repo_path
=
GIT_BUF_INIT
,
wd_path
=
GIT_BUF_INIT
,
common_path
=
GIT_BUF_INIT
,
head_path
=
GIT_BUF_INIT
;
common_path
=
GIT_BUF_INIT
;
const
char
*
wd
;
bool
is_valid
;
int
error
;
...
...
@@ -2125,16 +2159,7 @@ int git_repository_init_ext(
}
else
{
if
((
error
=
repo_init_structure
(
repo_path
.
ptr
,
wd
,
opts
))
<
0
||
(
error
=
repo_init_config
(
repo_path
.
ptr
,
wd
,
opts
->
flags
,
opts
->
mode
))
<
0
||
(
error
=
git_buf_joinpath
(
&
head_path
,
repo_path
.
ptr
,
GIT_HEAD_FILE
))
<
0
)
goto
out
;
/*
* Only set the new HEAD if the file does not exist already via
* a template or if the caller has explicitly supplied an
* initial HEAD value.
*/
if
((
!
git_path_exists
(
head_path
.
ptr
)
||
opts
->
initial_head
)
&&
(
error
=
git_repository_create_head
(
repo_path
.
ptr
,
opts
->
initial_head
))
<
0
)
(
error
=
repo_init_head
(
repo_path
.
ptr
,
opts
->
initial_head
))
<
0
)
goto
out
;
}
...
...
@@ -2146,7 +2171,6 @@ int git_repository_init_ext(
goto
out
;
out:
git_buf_dispose
(
&
head_path
);
git_buf_dispose
(
&
common_path
);
git_buf_dispose
(
&
repo_path
);
git_buf_dispose
(
&
wd_path
);
...
...
@@ -2330,23 +2354,59 @@ static int repo_contains_no_reference(git_repository *repo)
return
error
;
}
int
git_repository_initialbranch
(
git_buf
*
out
,
git_repository
*
repo
)
{
git_config
*
config
;
git_config_entry
*
entry
=
NULL
;
const
char
*
branch
;
int
error
;
if
((
error
=
git_repository_config__weakptr
(
&
config
,
repo
))
<
0
)
return
error
;
if
((
error
=
git_config_get_entry
(
&
entry
,
config
,
"init.defaultbranch"
))
==
0
)
{
branch
=
entry
->
value
;
}
else
if
(
error
==
GIT_ENOTFOUND
)
{
branch
=
GIT_BRANCH_DEFAULT
;
}
else
{
goto
done
;
}
if
((
error
=
git_buf_puts
(
out
,
GIT_REFS_HEADS_DIR
))
<
0
||
(
error
=
git_buf_puts
(
out
,
branch
))
<
0
)
goto
done
;
if
(
!
git_reference_is_valid_name
(
out
->
ptr
))
{
git_error_set
(
GIT_ERROR_INVALID
,
"the value of init.defaultBranch is not a valid reference name"
);
error
=
-
1
;
}
done:
git_config_entry_free
(
entry
);
return
error
;
}
int
git_repository_is_empty
(
git_repository
*
repo
)
{
git_reference
*
head
=
NULL
;
int
is_empty
=
0
;
git_buf
initialbranch
=
GIT_BUF_INIT
;
int
result
=
0
;
if
(
git_reference_lookup
(
&
head
,
repo
,
GIT_HEAD_FILE
)
<
0
)
return
-
1
;
if
((
result
=
git_reference_lookup
(
&
head
,
repo
,
GIT_HEAD_FILE
))
<
0
||
(
result
=
git_repository_initialbranch
(
&
initialbranch
,
repo
))
<
0
)
goto
done
;
if
(
git_reference_type
(
head
)
==
GIT_REFERENCE_SYMBOLIC
)
is_empty
=
(
strcmp
(
git_reference_symbolic_target
(
head
),
GIT_REFS_HEADS_DIR
"master"
)
==
0
)
&&
repo_contains_no_reference
(
repo
);
result
=
(
git_reference_type
(
head
)
==
GIT_REFERENCE_SYMBOLIC
&&
strcmp
(
git_reference_symbolic_target
(
head
),
initialbranch
.
ptr
)
==
0
&&
repo_contains_no_reference
(
repo
));
done:
git_reference_free
(
head
);
git_buf_dispose
(
&
initialbranch
);
return
is_empty
;
return
result
;
}
static
const
char
*
resolved_parent_path
(
const
git_repository
*
repo
,
git_repository_item_t
item
,
git_repository_item_t
fallback
)
...
...
src/repository.h
View file @
3a72345b
...
...
@@ -232,4 +232,10 @@ extern size_t git_repository__reserved_names_posix_len;
bool
git_repository__reserved_names
(
git_buf
**
out
,
size_t
*
outlen
,
git_repository
*
repo
,
bool
include_ntfs
);
/*
* The default branch for the repository; the `init.defaultBranch`
* configuration option, if set, or `master` if it is not.
*/
int
git_repository_initialbranch
(
git_buf
*
out
,
git_repository
*
repo
);
#endif
tests/clone/empty.c
View file @
3a72345b
...
...
@@ -2,6 +2,7 @@
#include "git2/clone.h"
#include "repository.h"
#include "repo/repo_helpers.h"
static
git_clone_options
g_options
;
static
git_repository
*
g_repo
;
...
...
@@ -22,6 +23,7 @@ void test_clone_empty__initialize(void)
void
test_clone_empty__cleanup
(
void
)
{
cl_fixture_cleanup
(
"tmp_global_path"
);
cl_git_sandbox_cleanup
();
}
...
...
@@ -66,6 +68,21 @@ void test_clone_empty__can_clone_an_empty_local_repo_barely(void)
expected_tracked_branch_name
));
}
void
test_clone_empty__respects_initialbranch_config
(
void
)
{
git_buf
buf
=
GIT_BUF_INIT
;
create_tmp_global_config
(
"tmp_global_path"
,
"init.defaultbranch"
,
"my_default_branch"
);
cl_set_cleanup
(
&
cleanup_repository
,
"./empty"
);
g_options
.
bare
=
true
;
cl_git_pass
(
git_clone
(
&
g_repo_cloned
,
"./empty_bare.git"
,
"./empty"
,
&
g_options
));
cl_git_pass
(
git_branch_upstream_name
(
&
buf
,
g_repo_cloned
,
"refs/heads/my_default_branch"
));
cl_assert_equal_s
(
"refs/remotes/origin/my_default_branch"
,
buf
.
ptr
);
git_buf_dispose
(
&
buf
);
}
void
test_clone_empty__can_clone_an_empty_local_repo
(
void
)
{
cl_set_cleanup
(
&
cleanup_repository
,
"./empty"
);
...
...
tests/repo/init.c
View file @
3a72345b
...
...
@@ -665,3 +665,19 @@ void test_repo_init__unwriteable_directory(void)
clar__skip
();
#endif
}
void
test_repo_init__defaultbranch_config
(
void
)
{
git_reference
*
head
;
cl_set_cleanup
(
&
cleanup_repository
,
"repo"
);
create_tmp_global_config
(
"tmp_global_path"
,
"init.defaultbranch"
,
"my_default_branch"
);
cl_git_pass
(
git_repository_init
(
&
_repo
,
"repo"
,
0
));
cl_git_pass
(
git_reference_lookup
(
&
head
,
_repo
,
"HEAD"
));
cl_assert_equal_s
(
"refs/heads/my_default_branch"
,
git_reference_symbolic_target
(
head
));
git_reference_free
(
head
);
}
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