rugged 0.17.0.b6 → 0.17.0.b7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.md +3 -3
- data/Rakefile +3 -1
- data/ext/rugged/rugged.c +30 -0
- data/ext/rugged/rugged.h +9 -0
- data/ext/rugged/rugged_branch.c +306 -0
- data/ext/rugged/rugged_config.c +16 -13
- data/ext/rugged/rugged_index.c +25 -0
- data/ext/rugged/rugged_object.c +6 -2
- data/ext/rugged/rugged_reference.c +11 -18
- data/ext/rugged/rugged_revwalk.c +1 -1
- data/lib/rugged.rb +1 -0
- data/lib/rugged/branch.rb +28 -0
- data/lib/rugged/commit.rb +5 -5
- data/lib/rugged/repository.rb +32 -7
- data/lib/rugged/tag.rb +5 -1
- data/lib/rugged/version.rb +1 -1
- data/test/branch_test.rb +227 -0
- data/test/config_test.rb +1 -1
- data/test/fixtures/testrepo.git/objects/4b/825dc642cb6eb9a060e54bf8d69288fbee4904 +0 -0
- data/test/fixtures/testrepo.git/objects/a3/e05719b428a2d0ed7a55c4ce53dcc5768c6d5e +0 -0
- data/test/index_test.rb +31 -0
- data/test/index_test.rb~ +218 -0
- data/test/lib_test.rb +22 -0
- data/test/reference_test.rb +5 -3
- data/vendor/libgit2/Makefile.embed +1 -1
- data/vendor/libgit2/include/git2.h +1 -0
- data/vendor/libgit2/include/git2/branch.h +17 -13
- data/vendor/libgit2/include/git2/checkout.h +83 -22
- data/vendor/libgit2/include/git2/clone.h +6 -3
- data/vendor/libgit2/include/git2/common.h +1 -8
- data/vendor/libgit2/include/git2/config.h +185 -26
- data/vendor/libgit2/include/git2/diff.h +229 -17
- data/vendor/libgit2/include/git2/errors.h +39 -1
- data/vendor/libgit2/include/git2/ignore.h +6 -3
- data/vendor/libgit2/include/git2/indexer.h +1 -0
- data/vendor/libgit2/include/git2/merge.h +1 -1
- data/vendor/libgit2/include/git2/object.h +7 -4
- data/vendor/libgit2/include/git2/odb.h +4 -2
- data/vendor/libgit2/include/git2/odb_backend.h +6 -0
- data/vendor/libgit2/include/git2/oid.h +2 -0
- data/vendor/libgit2/include/git2/pack.h +89 -0
- data/vendor/libgit2/include/git2/refs.h +88 -0
- data/vendor/libgit2/include/git2/refspec.h +0 -8
- data/vendor/libgit2/include/git2/remote.h +34 -1
- data/vendor/libgit2/include/git2/repository.h +238 -6
- data/vendor/libgit2/include/git2/reset.h +4 -1
- data/vendor/libgit2/include/git2/revwalk.h +1 -1
- data/vendor/libgit2/include/git2/status.h +19 -14
- data/vendor/libgit2/include/git2/strarray.h +54 -0
- data/vendor/libgit2/include/git2/submodule.h +451 -45
- data/vendor/libgit2/include/git2/tag.h +16 -0
- data/vendor/libgit2/include/git2/tree.h +2 -2
- data/vendor/libgit2/include/git2/types.h +4 -0
- data/vendor/libgit2/src/amiga/map.c +4 -7
- data/vendor/libgit2/src/attr.c +21 -13
- data/vendor/libgit2/src/attr.h +3 -1
- data/vendor/libgit2/src/attr_file.c +14 -14
- data/vendor/libgit2/src/attr_file.h +6 -5
- data/vendor/libgit2/src/blob.c +22 -12
- data/vendor/libgit2/src/branch.c +62 -66
- data/vendor/libgit2/src/buffer.c +63 -14
- data/vendor/libgit2/src/buffer.h +4 -0
- data/vendor/libgit2/src/cache.c +5 -4
- data/vendor/libgit2/src/checkout.c +381 -159
- data/vendor/libgit2/src/clone.c +221 -94
- data/vendor/libgit2/src/common.h +13 -3
- data/vendor/libgit2/src/compress.c +53 -0
- data/vendor/libgit2/src/compress.h +16 -0
- data/vendor/libgit2/src/config.c +380 -175
- data/vendor/libgit2/src/config.h +2 -5
- data/vendor/libgit2/src/config_file.c +63 -46
- data/vendor/libgit2/src/config_file.h +16 -4
- data/vendor/libgit2/src/crlf.c +4 -3
- data/vendor/libgit2/src/delta.c +491 -0
- data/vendor/libgit2/src/delta.h +112 -0
- data/vendor/libgit2/src/diff.c +310 -67
- data/vendor/libgit2/src/diff.h +10 -1
- data/vendor/libgit2/src/diff_output.c +1030 -337
- data/vendor/libgit2/src/diff_output.h +86 -0
- data/vendor/libgit2/src/errors.c +10 -1
- data/vendor/libgit2/src/fetch.c +108 -24
- data/vendor/libgit2/src/filebuf.c +8 -2
- data/vendor/libgit2/src/fileops.c +342 -177
- data/vendor/libgit2/src/fileops.h +84 -7
- data/vendor/libgit2/src/filter.c +0 -35
- data/vendor/libgit2/src/filter.h +0 -12
- data/vendor/libgit2/src/{compat/fnmatch.c → fnmatch.c} +16 -4
- data/vendor/libgit2/src/{compat/fnmatch.h → fnmatch.h} +4 -3
- data/vendor/libgit2/src/global.c +4 -0
- data/vendor/libgit2/src/ignore.c +122 -23
- data/vendor/libgit2/src/ignore.h +1 -0
- data/vendor/libgit2/src/index.c +56 -10
- data/vendor/libgit2/src/index.h +2 -0
- data/vendor/libgit2/src/indexer.c +8 -9
- data/vendor/libgit2/src/iterator.c +244 -31
- data/vendor/libgit2/src/iterator.h +30 -1
- data/vendor/libgit2/src/message.c +1 -1
- data/vendor/libgit2/src/netops.c +44 -4
- data/vendor/libgit2/src/object.c +80 -69
- data/vendor/libgit2/src/object.h +39 -0
- data/vendor/libgit2/src/odb.c +79 -15
- data/vendor/libgit2/src/odb.h +20 -5
- data/vendor/libgit2/src/odb_pack.c +65 -33
- data/vendor/libgit2/src/oid.c +0 -3
- data/vendor/libgit2/src/pack-objects.c +1315 -0
- data/vendor/libgit2/src/pack-objects.h +87 -0
- data/vendor/libgit2/src/pack.c +36 -12
- data/vendor/libgit2/src/pack.h +1 -0
- data/vendor/libgit2/src/path.c +42 -9
- data/vendor/libgit2/src/path.h +14 -0
- data/vendor/libgit2/src/pkt.c +52 -2
- data/vendor/libgit2/src/pkt.h +10 -0
- data/vendor/libgit2/src/pool.h +11 -0
- data/vendor/libgit2/src/posix.h +8 -0
- data/vendor/libgit2/src/protocol.c +24 -2
- data/vendor/libgit2/src/protocol.h +4 -0
- data/vendor/libgit2/src/reflog.c +1 -1
- data/vendor/libgit2/src/refs.c +292 -124
- data/vendor/libgit2/src/refs.h +4 -2
- data/vendor/libgit2/src/refspec.c +117 -19
- data/vendor/libgit2/src/refspec.h +19 -0
- data/vendor/libgit2/src/remote.c +152 -48
- data/vendor/libgit2/src/remote.h +4 -1
- data/vendor/libgit2/src/repo_template.h +58 -0
- data/vendor/libgit2/src/repository.c +594 -179
- data/vendor/libgit2/src/repository.h +23 -22
- data/vendor/libgit2/src/reset.c +71 -29
- data/vendor/libgit2/src/revparse.c +26 -17
- data/vendor/libgit2/src/revwalk.c +36 -19
- data/vendor/libgit2/src/sha1.h +7 -0
- data/vendor/libgit2/src/{sha1.c → sha1/sha1.c} +0 -0
- data/vendor/libgit2/src/signature.c +12 -10
- data/vendor/libgit2/src/status.c +52 -6
- data/vendor/libgit2/src/submodule.c +1363 -255
- data/vendor/libgit2/src/submodule.h +102 -0
- data/vendor/libgit2/src/tag.c +42 -26
- data/vendor/libgit2/src/thread-utils.h +7 -7
- data/vendor/libgit2/src/transport.h +15 -1
- data/vendor/libgit2/src/transports/git.c +1 -1
- data/vendor/libgit2/src/transports/http.c +197 -36
- data/vendor/libgit2/src/tree.c +3 -3
- data/vendor/libgit2/src/unix/map.c +2 -0
- data/vendor/libgit2/src/unix/posix.h +1 -8
- data/vendor/libgit2/src/util.c +6 -1
- data/vendor/libgit2/src/util.h +7 -0
- data/vendor/libgit2/src/vector.c +16 -0
- data/vendor/libgit2/src/vector.h +1 -0
- data/vendor/libgit2/src/win32/dir.c +8 -21
- data/vendor/libgit2/src/win32/findfile.c +149 -0
- data/vendor/libgit2/src/win32/findfile.h +23 -0
- data/vendor/libgit2/src/win32/posix.h +3 -7
- data/vendor/libgit2/src/win32/posix_w32.c +44 -102
- data/vendor/libgit2/src/win32/pthread.c +68 -0
- data/vendor/libgit2/src/win32/pthread.h +7 -0
- data/vendor/libgit2/src/win32/utf-conv.c +60 -71
- data/vendor/libgit2/src/win32/utf-conv.h +4 -3
- metadata +70 -71
- data/vendor/libgit2/include/git2/windows.h +0 -59
data/vendor/libgit2/src/remote.h
CHANGED
|
@@ -13,6 +13,8 @@
|
|
|
13
13
|
#include "transport.h"
|
|
14
14
|
#include "repository.h"
|
|
15
15
|
|
|
16
|
+
#define GIT_REMOTE_ORIGIN "origin"
|
|
17
|
+
|
|
16
18
|
struct git_remote {
|
|
17
19
|
char *name;
|
|
18
20
|
char *url;
|
|
@@ -24,7 +26,8 @@ struct git_remote {
|
|
|
24
26
|
git_repository *repo;
|
|
25
27
|
git_remote_callbacks callbacks;
|
|
26
28
|
unsigned int need_pack:1,
|
|
27
|
-
|
|
29
|
+
download_tags:2, /* There are four possible values */
|
|
30
|
+
check_cert:1;
|
|
28
31
|
};
|
|
29
32
|
|
|
30
33
|
const char* git_remote__urlfordirection(struct git_remote *remote, int direction);
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (C) 2012 the libgit2 contributors
|
|
3
|
+
*
|
|
4
|
+
* This file is part of libgit2, distributed under the GNU GPL v2 with
|
|
5
|
+
* a Linking Exception. For full terms see the included COPYING file.
|
|
6
|
+
*/
|
|
7
|
+
#ifndef INCLUDE_repo_template_h__
|
|
8
|
+
#define INCLUDE_repo_template_h__
|
|
9
|
+
|
|
10
|
+
#define GIT_OBJECTS_INFO_DIR GIT_OBJECTS_DIR "info/"
|
|
11
|
+
#define GIT_OBJECTS_PACK_DIR GIT_OBJECTS_DIR "pack/"
|
|
12
|
+
|
|
13
|
+
#define GIT_HOOKS_DIR "hooks/"
|
|
14
|
+
#define GIT_HOOKS_DIR_MODE 0755
|
|
15
|
+
|
|
16
|
+
#define GIT_HOOKS_README_FILE GIT_HOOKS_DIR "README.sample"
|
|
17
|
+
#define GIT_HOOKS_README_MODE 0755
|
|
18
|
+
#define GIT_HOOKS_README_CONTENT \
|
|
19
|
+
"#!/bin/sh\n"\
|
|
20
|
+
"#\n"\
|
|
21
|
+
"# Place appropriately named executable hook scripts into this directory\n"\
|
|
22
|
+
"# to intercept various actions that git takes. See `git help hooks` for\n"\
|
|
23
|
+
"# more information.\n"
|
|
24
|
+
|
|
25
|
+
#define GIT_INFO_DIR "info/"
|
|
26
|
+
#define GIT_INFO_DIR_MODE 0755
|
|
27
|
+
|
|
28
|
+
#define GIT_INFO_EXCLUDE_FILE GIT_INFO_DIR "exclude"
|
|
29
|
+
#define GIT_INFO_EXCLUDE_MODE 0644
|
|
30
|
+
#define GIT_INFO_EXCLUDE_CONTENT \
|
|
31
|
+
"# File patterns to ignore; see `git help ignore` for more information.\n"\
|
|
32
|
+
"# Lines that start with '#' are comments.\n"
|
|
33
|
+
|
|
34
|
+
#define GIT_DESC_FILE "description"
|
|
35
|
+
#define GIT_DESC_MODE 0644
|
|
36
|
+
#define GIT_DESC_CONTENT \
|
|
37
|
+
"Unnamed repository; edit this file 'description' to name the repository.\n"
|
|
38
|
+
|
|
39
|
+
typedef struct {
|
|
40
|
+
const char *path;
|
|
41
|
+
mode_t mode;
|
|
42
|
+
const char *content;
|
|
43
|
+
} repo_template_item;
|
|
44
|
+
|
|
45
|
+
static repo_template_item repo_template[] = {
|
|
46
|
+
{ GIT_OBJECTS_INFO_DIR, GIT_OBJECT_DIR_MODE, NULL }, /* '/objects/info/' */
|
|
47
|
+
{ GIT_OBJECTS_PACK_DIR, GIT_OBJECT_DIR_MODE, NULL }, /* '/objects/pack/' */
|
|
48
|
+
{ GIT_REFS_HEADS_DIR, GIT_REFS_DIR_MODE, NULL }, /* '/refs/heads/' */
|
|
49
|
+
{ GIT_REFS_TAGS_DIR, GIT_REFS_DIR_MODE, NULL }, /* '/refs/tags/' */
|
|
50
|
+
{ GIT_HOOKS_DIR, GIT_HOOKS_DIR_MODE, NULL }, /* '/hooks/' */
|
|
51
|
+
{ GIT_INFO_DIR, GIT_INFO_DIR_MODE, NULL }, /* '/info/' */
|
|
52
|
+
{ GIT_DESC_FILE, GIT_DESC_MODE, GIT_DESC_CONTENT },
|
|
53
|
+
{ GIT_HOOKS_README_FILE, GIT_HOOKS_README_MODE, GIT_HOOKS_README_CONTENT },
|
|
54
|
+
{ GIT_INFO_EXCLUDE_FILE, GIT_INFO_EXCLUDE_MODE, GIT_INFO_EXCLUDE_CONTENT },
|
|
55
|
+
{ NULL, 0, NULL }
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
#endif
|
|
@@ -17,9 +17,9 @@
|
|
|
17
17
|
#include "fileops.h"
|
|
18
18
|
#include "config.h"
|
|
19
19
|
#include "refs.h"
|
|
20
|
-
|
|
21
|
-
#
|
|
22
|
-
#
|
|
20
|
+
#include "filter.h"
|
|
21
|
+
#include "odb.h"
|
|
22
|
+
#include "remote.h"
|
|
23
23
|
|
|
24
24
|
#define GIT_FILE_CONTENT_PREFIX "gitdir:"
|
|
25
25
|
|
|
@@ -27,6 +27,8 @@
|
|
|
27
27
|
|
|
28
28
|
#define GIT_REPO_VERSION 0
|
|
29
29
|
|
|
30
|
+
#define GIT_TEMPLATE_DIR "/usr/share/git-core/templates"
|
|
31
|
+
|
|
30
32
|
static void drop_odb(git_repository *repo)
|
|
31
33
|
{
|
|
32
34
|
if (repo->_odb != NULL) {
|
|
@@ -147,8 +149,13 @@ static int load_workdir(git_repository *repo, git_buf *parent_path)
|
|
|
147
149
|
return -1;
|
|
148
150
|
|
|
149
151
|
error = git_config_get_string(&worktree, config, "core.worktree");
|
|
150
|
-
if (!error && worktree != NULL)
|
|
151
|
-
|
|
152
|
+
if (!error && worktree != NULL) {
|
|
153
|
+
error = git_path_prettify_dir(
|
|
154
|
+
&worktree_buf, worktree, repo->path_repository);
|
|
155
|
+
if (error < 0)
|
|
156
|
+
return error;
|
|
157
|
+
repo->workdir = git_buf_detach(&worktree_buf);
|
|
158
|
+
}
|
|
152
159
|
else if (error != GIT_ENOTFOUND)
|
|
153
160
|
return error;
|
|
154
161
|
else {
|
|
@@ -238,16 +245,17 @@ static int read_gitfile(git_buf *path_out, const char *file_path)
|
|
|
238
245
|
|
|
239
246
|
git_buf_rtrim(&file);
|
|
240
247
|
|
|
241
|
-
if (file
|
|
242
|
-
memcmp(file
|
|
248
|
+
if (git_buf_len(&file) <= prefix_len ||
|
|
249
|
+
memcmp(git_buf_cstr(&file), GIT_FILE_CONTENT_PREFIX, prefix_len) != 0)
|
|
243
250
|
{
|
|
244
251
|
giterr_set(GITERR_REPOSITORY, "The `.git` file at '%s' is malformed", file_path);
|
|
245
252
|
error = -1;
|
|
246
253
|
}
|
|
247
254
|
else if ((error = git_path_dirname_r(path_out, file_path)) >= 0) {
|
|
248
|
-
const char *gitlink = (
|
|
255
|
+
const char *gitlink = git_buf_cstr(&file) + prefix_len;
|
|
249
256
|
while (*gitlink && git__isspace(*gitlink)) gitlink++;
|
|
250
|
-
error = git_path_prettify_dir(
|
|
257
|
+
error = git_path_prettify_dir(
|
|
258
|
+
path_out, gitlink, git_buf_cstr(path_out));
|
|
251
259
|
}
|
|
252
260
|
|
|
253
261
|
git_buf_free(&file);
|
|
@@ -359,9 +367,11 @@ int git_repository_open_ext(
|
|
|
359
367
|
git_buf path = GIT_BUF_INIT, parent = GIT_BUF_INIT;
|
|
360
368
|
git_repository *repo;
|
|
361
369
|
|
|
362
|
-
|
|
370
|
+
if (repo_ptr)
|
|
371
|
+
*repo_ptr = NULL;
|
|
363
372
|
|
|
364
|
-
|
|
373
|
+
error = find_repo(&path, &parent, start_path, flags, ceiling_dirs);
|
|
374
|
+
if (error < 0 || !repo_ptr)
|
|
365
375
|
return error;
|
|
366
376
|
|
|
367
377
|
repo = repository_alloc();
|
|
@@ -421,7 +431,7 @@ int git_repository_discover(
|
|
|
421
431
|
|
|
422
432
|
if (size < (size_t)(path.size + 1)) {
|
|
423
433
|
giterr_set(GITERR_REPOSITORY,
|
|
424
|
-
"The given buffer is too
|
|
434
|
+
"The given buffer is too small to store the discovered path");
|
|
425
435
|
git_buf_free(&path);
|
|
426
436
|
return -1;
|
|
427
437
|
}
|
|
@@ -436,6 +446,7 @@ static int load_config(
|
|
|
436
446
|
git_config **out,
|
|
437
447
|
git_repository *repo,
|
|
438
448
|
const char *global_config_path,
|
|
449
|
+
const char *xdg_config_path,
|
|
439
450
|
const char *system_config_path)
|
|
440
451
|
{
|
|
441
452
|
git_buf config_path = GIT_BUF_INIT;
|
|
@@ -450,18 +461,23 @@ static int load_config(
|
|
|
450
461
|
&config_path, repo->path_repository, GIT_CONFIG_FILENAME_INREPO) < 0)
|
|
451
462
|
goto on_error;
|
|
452
463
|
|
|
453
|
-
if (git_config_add_file_ondisk(cfg, config_path.ptr,
|
|
464
|
+
if (git_config_add_file_ondisk(cfg, config_path.ptr, GIT_CONFIG_LEVEL_LOCAL, 0) < 0)
|
|
454
465
|
goto on_error;
|
|
455
466
|
|
|
456
467
|
git_buf_free(&config_path);
|
|
457
468
|
|
|
458
469
|
if (global_config_path != NULL) {
|
|
459
|
-
if (git_config_add_file_ondisk(cfg, global_config_path,
|
|
470
|
+
if (git_config_add_file_ondisk(cfg, global_config_path, GIT_CONFIG_LEVEL_GLOBAL, 0) < 0)
|
|
471
|
+
goto on_error;
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
if (xdg_config_path != NULL) {
|
|
475
|
+
if (git_config_add_file_ondisk(cfg, xdg_config_path, GIT_CONFIG_LEVEL_XDG, 0) < 0)
|
|
460
476
|
goto on_error;
|
|
461
477
|
}
|
|
462
478
|
|
|
463
479
|
if (system_config_path != NULL) {
|
|
464
|
-
if (git_config_add_file_ondisk(cfg, system_config_path,
|
|
480
|
+
if (git_config_add_file_ondisk(cfg, system_config_path, GIT_CONFIG_LEVEL_SYSTEM, 0) < 0)
|
|
465
481
|
goto on_error;
|
|
466
482
|
}
|
|
467
483
|
|
|
@@ -478,21 +494,26 @@ on_error:
|
|
|
478
494
|
int git_repository_config__weakptr(git_config **out, git_repository *repo)
|
|
479
495
|
{
|
|
480
496
|
if (repo->_config == NULL) {
|
|
481
|
-
git_buf global_buf = GIT_BUF_INIT, system_buf = GIT_BUF_INIT;
|
|
497
|
+
git_buf global_buf = GIT_BUF_INIT, xdg_buf = GIT_BUF_INIT, system_buf = GIT_BUF_INIT;
|
|
482
498
|
int res;
|
|
483
499
|
|
|
484
500
|
const char *global_config_path = NULL;
|
|
501
|
+
const char *xdg_config_path = NULL;
|
|
485
502
|
const char *system_config_path = NULL;
|
|
486
503
|
|
|
487
504
|
if (git_config_find_global_r(&global_buf) == 0)
|
|
488
505
|
global_config_path = global_buf.ptr;
|
|
489
506
|
|
|
507
|
+
if (git_config_find_xdg_r(&xdg_buf) == 0)
|
|
508
|
+
xdg_config_path = xdg_buf.ptr;
|
|
509
|
+
|
|
490
510
|
if (git_config_find_system_r(&system_buf) == 0)
|
|
491
511
|
system_config_path = system_buf.ptr;
|
|
492
512
|
|
|
493
|
-
res = load_config(&repo->_config, repo, global_config_path, system_config_path);
|
|
513
|
+
res = load_config(&repo->_config, repo, global_config_path, xdg_config_path, system_config_path);
|
|
494
514
|
|
|
495
515
|
git_buf_free(&global_buf);
|
|
516
|
+
git_buf_free(&xdg_buf);
|
|
496
517
|
git_buf_free(&system_buf);
|
|
497
518
|
|
|
498
519
|
if (res < 0)
|
|
@@ -632,19 +653,35 @@ static int check_repositoryformatversion(git_config *config)
|
|
|
632
653
|
return 0;
|
|
633
654
|
}
|
|
634
655
|
|
|
635
|
-
static int
|
|
656
|
+
static int repo_init_create_head(const char *git_dir, const char *ref_name)
|
|
636
657
|
{
|
|
637
658
|
git_buf ref_path = GIT_BUF_INIT;
|
|
638
659
|
git_filebuf ref = GIT_FILEBUF_INIT;
|
|
660
|
+
const char *fmt;
|
|
639
661
|
|
|
640
662
|
if (git_buf_joinpath(&ref_path, git_dir, GIT_HEAD_FILE) < 0 ||
|
|
641
|
-
git_filebuf_open(&ref, ref_path.ptr, 0) < 0
|
|
642
|
-
|
|
663
|
+
git_filebuf_open(&ref, ref_path.ptr, 0) < 0)
|
|
664
|
+
goto fail;
|
|
665
|
+
|
|
666
|
+
if (!ref_name)
|
|
667
|
+
ref_name = GIT_BRANCH_MASTER;
|
|
668
|
+
|
|
669
|
+
if (git__prefixcmp(ref_name, GIT_REFS_DIR) == 0)
|
|
670
|
+
fmt = "ref: %s\n";
|
|
671
|
+
else
|
|
672
|
+
fmt = "ref: " GIT_REFS_HEADS_DIR "%s\n";
|
|
673
|
+
|
|
674
|
+
if (git_filebuf_printf(&ref, fmt, ref_name) < 0 ||
|
|
643
675
|
git_filebuf_commit(&ref, GIT_REFS_FILE_MODE) < 0)
|
|
644
|
-
|
|
676
|
+
goto fail;
|
|
645
677
|
|
|
646
678
|
git_buf_free(&ref_path);
|
|
647
679
|
return 0;
|
|
680
|
+
|
|
681
|
+
fail:
|
|
682
|
+
git_buf_free(&ref_path);
|
|
683
|
+
git_filebuf_cleanup(&ref);
|
|
684
|
+
return -1;
|
|
648
685
|
}
|
|
649
686
|
|
|
650
687
|
static bool is_chmod_supported(const char *file_path)
|
|
@@ -665,6 +702,7 @@ static bool is_chmod_supported(const char *file_path)
|
|
|
665
702
|
return false;
|
|
666
703
|
|
|
667
704
|
_is_supported = (st1.st_mode != st2.st_mode);
|
|
705
|
+
|
|
668
706
|
return _is_supported;
|
|
669
707
|
}
|
|
670
708
|
|
|
@@ -686,19 +724,45 @@ cleanup:
|
|
|
686
724
|
return _is_insensitive;
|
|
687
725
|
}
|
|
688
726
|
|
|
689
|
-
static
|
|
727
|
+
static bool are_symlinks_supported(const char *wd_path)
|
|
728
|
+
{
|
|
729
|
+
git_buf path = GIT_BUF_INIT;
|
|
730
|
+
int fd;
|
|
731
|
+
struct stat st;
|
|
732
|
+
static int _symlinks_supported = -1;
|
|
733
|
+
|
|
734
|
+
if (_symlinks_supported > -1)
|
|
735
|
+
return _symlinks_supported;
|
|
736
|
+
|
|
737
|
+
if ((fd = git_futils_mktmp(&path, wd_path)) < 0 ||
|
|
738
|
+
p_close(fd) < 0 ||
|
|
739
|
+
p_unlink(path.ptr) < 0 ||
|
|
740
|
+
p_symlink("testing", path.ptr) < 0 ||
|
|
741
|
+
p_lstat(path.ptr, &st) < 0)
|
|
742
|
+
_symlinks_supported = false;
|
|
743
|
+
else
|
|
744
|
+
_symlinks_supported = (S_ISLNK(st.st_mode) != 0);
|
|
745
|
+
|
|
746
|
+
(void)p_unlink(path.ptr);
|
|
747
|
+
git_buf_free(&path);
|
|
748
|
+
|
|
749
|
+
return _symlinks_supported;
|
|
750
|
+
}
|
|
751
|
+
|
|
752
|
+
static int repo_init_config(
|
|
753
|
+
const char *repo_dir,
|
|
754
|
+
const char *work_dir,
|
|
755
|
+
git_repository_init_options *opts)
|
|
690
756
|
{
|
|
757
|
+
int error = 0;
|
|
691
758
|
git_buf cfg_path = GIT_BUF_INIT;
|
|
692
759
|
git_config *config = NULL;
|
|
693
760
|
|
|
694
|
-
#define SET_REPO_CONFIG(
|
|
695
|
-
if (git_config_set_##
|
|
696
|
-
|
|
697
|
-
git_config_free(config); \
|
|
698
|
-
return -1; } \
|
|
699
|
-
}
|
|
761
|
+
#define SET_REPO_CONFIG(TYPE, NAME, VAL) do {\
|
|
762
|
+
if ((error = git_config_set_##TYPE(config, NAME, VAL)) < 0) \
|
|
763
|
+
goto cleanup; } while (0)
|
|
700
764
|
|
|
701
|
-
if (git_buf_joinpath(&cfg_path,
|
|
765
|
+
if (git_buf_joinpath(&cfg_path, repo_dir, GIT_CONFIG_FILENAME_INREPO) < 0)
|
|
702
766
|
return -1;
|
|
703
767
|
|
|
704
768
|
if (git_config_open_ondisk(&config, git_buf_cstr(&cfg_path)) < 0) {
|
|
@@ -706,58 +770,61 @@ static int repo_init_config(const char *git_dir, bool is_bare, bool is_reinit)
|
|
|
706
770
|
return -1;
|
|
707
771
|
}
|
|
708
772
|
|
|
709
|
-
if (
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
return -1;
|
|
713
|
-
}
|
|
773
|
+
if ((opts->flags & GIT_REPOSITORY_INIT__IS_REINIT) != 0 &&
|
|
774
|
+
(error = check_repositoryformatversion(config)) < 0)
|
|
775
|
+
goto cleanup;
|
|
714
776
|
|
|
715
|
-
SET_REPO_CONFIG(
|
|
716
|
-
|
|
717
|
-
SET_REPO_CONFIG(
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
777
|
+
SET_REPO_CONFIG(
|
|
778
|
+
bool, "core.bare", (opts->flags & GIT_REPOSITORY_INIT_BARE) != 0);
|
|
779
|
+
SET_REPO_CONFIG(
|
|
780
|
+
int32, "core.repositoryformatversion", GIT_REPO_VERSION);
|
|
781
|
+
SET_REPO_CONFIG(
|
|
782
|
+
bool, "core.filemode", is_chmod_supported(git_buf_cstr(&cfg_path)));
|
|
721
783
|
|
|
722
|
-
if (!
|
|
723
|
-
SET_REPO_CONFIG(bool, "core.
|
|
724
|
-
/* TODO: what other defaults? */
|
|
784
|
+
if (!(opts->flags & GIT_REPOSITORY_INIT_BARE)) {
|
|
785
|
+
SET_REPO_CONFIG(bool, "core.logallrefupdates", true);
|
|
725
786
|
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
return 0;
|
|
729
|
-
}
|
|
787
|
+
if (!are_symlinks_supported(work_dir))
|
|
788
|
+
SET_REPO_CONFIG(bool, "core.symlinks", false);
|
|
730
789
|
|
|
731
|
-
|
|
732
|
-
|
|
790
|
+
if (!(opts->flags & GIT_REPOSITORY_INIT__NATURAL_WD)) {
|
|
791
|
+
SET_REPO_CONFIG(string, "core.worktree", work_dir);
|
|
792
|
+
}
|
|
793
|
+
else if ((opts->flags & GIT_REPOSITORY_INIT__IS_REINIT) != 0) {
|
|
794
|
+
if (git_config_delete(config, "core.worktree") < 0)
|
|
795
|
+
giterr_clear();
|
|
796
|
+
}
|
|
797
|
+
} else {
|
|
798
|
+
if (!are_symlinks_supported(repo_dir))
|
|
799
|
+
SET_REPO_CONFIG(bool, "core.symlinks", false);
|
|
800
|
+
}
|
|
733
801
|
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
"#!/bin/sh\n"\
|
|
738
|
-
"#\n"\
|
|
739
|
-
"# Place appropriately named executable hook scripts into this directory\n"\
|
|
740
|
-
"# to intercept various actions that git takes. See `git help hooks` for\n"\
|
|
741
|
-
"# more information.\n"
|
|
802
|
+
if (!(opts->flags & GIT_REPOSITORY_INIT__IS_REINIT) &&
|
|
803
|
+
is_filesystem_case_insensitive(repo_dir))
|
|
804
|
+
SET_REPO_CONFIG(bool, "core.ignorecase", true);
|
|
742
805
|
|
|
743
|
-
|
|
744
|
-
|
|
806
|
+
if (opts->mode == GIT_REPOSITORY_INIT_SHARED_GROUP) {
|
|
807
|
+
SET_REPO_CONFIG(int32, "core.sharedrepository", 1);
|
|
808
|
+
SET_REPO_CONFIG(bool, "receive.denyNonFastforwards", true);
|
|
809
|
+
}
|
|
810
|
+
else if (opts->mode == GIT_REPOSITORY_INIT_SHARED_ALL) {
|
|
811
|
+
SET_REPO_CONFIG(int32, "core.sharedrepository", 2);
|
|
812
|
+
SET_REPO_CONFIG(bool, "receive.denyNonFastforwards", true);
|
|
813
|
+
}
|
|
745
814
|
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
"# File patterns to ignore; see `git help ignore` for more information.\n"\
|
|
750
|
-
"# Lines that start with '#' are comments.\n"
|
|
815
|
+
cleanup:
|
|
816
|
+
git_buf_free(&cfg_path);
|
|
817
|
+
git_config_free(config);
|
|
751
818
|
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
#define GIT_DESC_CONTENT "Unnamed repository; edit this file 'description' to name the repository.\n"
|
|
819
|
+
return error;
|
|
820
|
+
}
|
|
755
821
|
|
|
756
822
|
static int repo_write_template(
|
|
757
823
|
const char *git_dir,
|
|
758
824
|
bool allow_overwrite,
|
|
759
825
|
const char *file,
|
|
760
826
|
mode_t mode,
|
|
827
|
+
bool hidden,
|
|
761
828
|
const char *content)
|
|
762
829
|
{
|
|
763
830
|
git_buf path = GIT_BUF_INIT;
|
|
@@ -781,6 +848,15 @@ static int repo_write_template(
|
|
|
781
848
|
else if (errno != EEXIST)
|
|
782
849
|
error = fd;
|
|
783
850
|
|
|
851
|
+
#ifdef GIT_WIN32
|
|
852
|
+
if (!error && hidden) {
|
|
853
|
+
if (p_hide_directory__w32(path.ptr) < 0)
|
|
854
|
+
error = -1;
|
|
855
|
+
}
|
|
856
|
+
#else
|
|
857
|
+
GIT_UNUSED(hidden);
|
|
858
|
+
#endif
|
|
859
|
+
|
|
784
860
|
git_buf_free(&path);
|
|
785
861
|
|
|
786
862
|
if (error)
|
|
@@ -790,86 +866,319 @@ static int repo_write_template(
|
|
|
790
866
|
return error;
|
|
791
867
|
}
|
|
792
868
|
|
|
793
|
-
static int
|
|
869
|
+
static int repo_write_gitlink(
|
|
870
|
+
const char *in_dir, const char *to_repo)
|
|
794
871
|
{
|
|
795
|
-
int
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
{ GIT_INFO_DIR, GIT_INFO_DIR_MODE }, /* '/info/' */
|
|
803
|
-
{ NULL, 0 }
|
|
804
|
-
};
|
|
805
|
-
struct { const char *file; mode_t mode; const char *content; } tmpl[] = {
|
|
806
|
-
{ GIT_DESC_FILE, GIT_DESC_MODE, GIT_DESC_CONTENT },
|
|
807
|
-
{ GIT_HOOKS_README_FILE, GIT_HOOKS_README_MODE, GIT_HOOKS_README_CONTENT },
|
|
808
|
-
{ GIT_INFO_EXCLUDE_FILE, GIT_INFO_EXCLUDE_MODE, GIT_INFO_EXCLUDE_CONTENT },
|
|
809
|
-
{ NULL, 0, NULL }
|
|
810
|
-
};
|
|
811
|
-
|
|
812
|
-
/* Make the base directory */
|
|
813
|
-
if (git_futils_mkdir_r(git_dir, NULL, is_bare ? GIT_BARE_DIR_MODE : GIT_DIR_MODE) < 0)
|
|
872
|
+
int error;
|
|
873
|
+
git_buf buf = GIT_BUF_INIT;
|
|
874
|
+
struct stat st;
|
|
875
|
+
|
|
876
|
+
git_path_dirname_r(&buf, to_repo);
|
|
877
|
+
git_path_to_dir(&buf);
|
|
878
|
+
if (git_buf_oom(&buf))
|
|
814
879
|
return -1;
|
|
815
880
|
|
|
816
|
-
/*
|
|
817
|
-
if (
|
|
881
|
+
/* don't write gitlink to natural workdir */
|
|
882
|
+
if (git__suffixcmp(to_repo, "/" DOT_GIT "/") == 0 &&
|
|
883
|
+
strcmp(in_dir, buf.ptr) == 0)
|
|
884
|
+
{
|
|
885
|
+
error = GIT_PASSTHROUGH;
|
|
886
|
+
goto cleanup;
|
|
887
|
+
}
|
|
888
|
+
|
|
889
|
+
if ((error = git_buf_joinpath(&buf, in_dir, DOT_GIT)) < 0)
|
|
890
|
+
goto cleanup;
|
|
891
|
+
|
|
892
|
+
if (!p_stat(buf.ptr, &st) && !S_ISREG(st.st_mode)) {
|
|
893
|
+
giterr_set(GITERR_REPOSITORY,
|
|
894
|
+
"Cannot overwrite gitlink file into path '%s'", in_dir);
|
|
895
|
+
error = GIT_EEXISTS;
|
|
896
|
+
goto cleanup;
|
|
897
|
+
}
|
|
898
|
+
|
|
899
|
+
git_buf_clear(&buf);
|
|
900
|
+
|
|
901
|
+
error = git_buf_printf(&buf, "%s %s", GIT_FILE_CONTENT_PREFIX, to_repo);
|
|
902
|
+
|
|
903
|
+
if (!error)
|
|
904
|
+
error = repo_write_template(in_dir, true, DOT_GIT, 0644, true, buf.ptr);
|
|
905
|
+
|
|
906
|
+
cleanup:
|
|
907
|
+
git_buf_free(&buf);
|
|
908
|
+
return error;
|
|
909
|
+
}
|
|
910
|
+
|
|
911
|
+
static mode_t pick_dir_mode(git_repository_init_options *opts)
|
|
912
|
+
{
|
|
913
|
+
if (opts->mode == GIT_REPOSITORY_INIT_SHARED_UMASK)
|
|
914
|
+
return 0755;
|
|
915
|
+
if (opts->mode == GIT_REPOSITORY_INIT_SHARED_GROUP)
|
|
916
|
+
return (0775 | S_ISGID);
|
|
917
|
+
if (opts->mode == GIT_REPOSITORY_INIT_SHARED_ALL)
|
|
918
|
+
return (0777 | S_ISGID);
|
|
919
|
+
return opts->mode;
|
|
920
|
+
}
|
|
921
|
+
|
|
922
|
+
#include "repo_template.h"
|
|
923
|
+
|
|
924
|
+
static int repo_init_structure(
|
|
925
|
+
const char *repo_dir,
|
|
926
|
+
const char *work_dir,
|
|
927
|
+
git_repository_init_options *opts)
|
|
928
|
+
{
|
|
929
|
+
int error = 0;
|
|
930
|
+
repo_template_item *tpl;
|
|
931
|
+
bool external_tpl =
|
|
932
|
+
((opts->flags & GIT_REPOSITORY_INIT_EXTERNAL_TEMPLATE) != 0);
|
|
933
|
+
mode_t dmode = pick_dir_mode(opts);
|
|
934
|
+
|
|
935
|
+
/* Hide the ".git" directory */
|
|
818
936
|
#ifdef GIT_WIN32
|
|
819
|
-
|
|
937
|
+
if ((opts->flags & GIT_REPOSITORY_INIT__HAS_DOTGIT) != 0) {
|
|
938
|
+
if (p_hide_directory__w32(repo_dir) < 0) {
|
|
820
939
|
giterr_set(GITERR_REPOSITORY,
|
|
821
940
|
"Failed to mark Git repository folder as hidden");
|
|
822
941
|
return -1;
|
|
823
942
|
}
|
|
824
|
-
#endif
|
|
825
943
|
}
|
|
944
|
+
#endif
|
|
826
945
|
|
|
827
|
-
/*
|
|
828
|
-
|
|
829
|
-
|
|
946
|
+
/* Create the .git gitlink if appropriate */
|
|
947
|
+
if ((opts->flags & GIT_REPOSITORY_INIT_BARE) == 0 &&
|
|
948
|
+
(opts->flags & GIT_REPOSITORY_INIT__NATURAL_WD) == 0)
|
|
949
|
+
{
|
|
950
|
+
if (repo_write_gitlink(work_dir, repo_dir) < 0)
|
|
830
951
|
return -1;
|
|
831
952
|
}
|
|
832
953
|
|
|
833
|
-
/*
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
954
|
+
/* Copy external template if requested */
|
|
955
|
+
if (external_tpl) {
|
|
956
|
+
git_config *cfg;
|
|
957
|
+
const char *tdir;
|
|
958
|
+
|
|
959
|
+
if (opts->template_path)
|
|
960
|
+
tdir = opts->template_path;
|
|
961
|
+
else if ((error = git_config_open_default(&cfg)) < 0)
|
|
962
|
+
return error;
|
|
963
|
+
else {
|
|
964
|
+
error = git_config_get_string(&tdir, cfg, "init.templatedir");
|
|
965
|
+
|
|
966
|
+
git_config_free(cfg);
|
|
967
|
+
|
|
968
|
+
if (error && error != GIT_ENOTFOUND)
|
|
969
|
+
return error;
|
|
970
|
+
|
|
971
|
+
giterr_clear();
|
|
972
|
+
tdir = GIT_TEMPLATE_DIR;
|
|
973
|
+
}
|
|
974
|
+
|
|
975
|
+
error = git_futils_cp_r(tdir, repo_dir,
|
|
976
|
+
GIT_CPDIR_COPY_SYMLINKS | GIT_CPDIR_CHMOD, dmode);
|
|
977
|
+
|
|
978
|
+
if (error < 0) {
|
|
979
|
+
if (strcmp(tdir, GIT_TEMPLATE_DIR) != 0)
|
|
980
|
+
return error;
|
|
981
|
+
|
|
982
|
+
/* if template was default, ignore error and use internal */
|
|
983
|
+
giterr_clear();
|
|
984
|
+
external_tpl = false;
|
|
985
|
+
}
|
|
986
|
+
}
|
|
987
|
+
|
|
988
|
+
/* Copy internal template
|
|
989
|
+
* - always ensure existence of dirs
|
|
990
|
+
* - only create files if no external template was specified
|
|
991
|
+
*/
|
|
992
|
+
for (tpl = repo_template; !error && tpl->path; ++tpl) {
|
|
993
|
+
if (!tpl->content)
|
|
994
|
+
error = git_futils_mkdir(
|
|
995
|
+
tpl->path, repo_dir, dmode, GIT_MKDIR_PATH | GIT_MKDIR_CHMOD);
|
|
996
|
+
else if (!external_tpl) {
|
|
997
|
+
const char *content = tpl->content;
|
|
998
|
+
|
|
999
|
+
if (opts->description && strcmp(tpl->path, GIT_DESC_FILE) == 0)
|
|
1000
|
+
content = opts->description;
|
|
1001
|
+
|
|
1002
|
+
error = repo_write_template(
|
|
1003
|
+
repo_dir, false, tpl->path, tpl->mode, false, content);
|
|
1004
|
+
}
|
|
1005
|
+
}
|
|
1006
|
+
|
|
1007
|
+
return error;
|
|
1008
|
+
}
|
|
1009
|
+
|
|
1010
|
+
static int repo_init_directories(
|
|
1011
|
+
git_buf *repo_path,
|
|
1012
|
+
git_buf *wd_path,
|
|
1013
|
+
const char *given_repo,
|
|
1014
|
+
git_repository_init_options *opts)
|
|
1015
|
+
{
|
|
1016
|
+
int error = 0;
|
|
1017
|
+
bool add_dotgit, has_dotgit, natural_wd;
|
|
1018
|
+
mode_t dirmode;
|
|
1019
|
+
|
|
1020
|
+
/* set up repo path */
|
|
1021
|
+
|
|
1022
|
+
add_dotgit =
|
|
1023
|
+
(opts->flags & GIT_REPOSITORY_INIT_NO_DOTGIT_DIR) == 0 &&
|
|
1024
|
+
(opts->flags & GIT_REPOSITORY_INIT_BARE) == 0 &&
|
|
1025
|
+
git__suffixcmp(given_repo, "/" DOT_GIT) != 0 &&
|
|
1026
|
+
git__suffixcmp(given_repo, "/" GIT_DIR) != 0;
|
|
1027
|
+
|
|
1028
|
+
if (git_buf_joinpath(repo_path, given_repo, add_dotgit ? GIT_DIR : "") < 0)
|
|
1029
|
+
return -1;
|
|
1030
|
+
|
|
1031
|
+
has_dotgit = (git__suffixcmp(repo_path->ptr, "/" GIT_DIR) == 0);
|
|
1032
|
+
if (has_dotgit)
|
|
1033
|
+
opts->flags |= GIT_REPOSITORY_INIT__HAS_DOTGIT;
|
|
1034
|
+
|
|
1035
|
+
/* set up workdir path */
|
|
1036
|
+
|
|
1037
|
+
if ((opts->flags & GIT_REPOSITORY_INIT_BARE) == 0) {
|
|
1038
|
+
if (opts->workdir_path) {
|
|
1039
|
+
if (git_path_join_unrooted(
|
|
1040
|
+
wd_path, opts->workdir_path, repo_path->ptr, NULL) < 0)
|
|
1041
|
+
return -1;
|
|
1042
|
+
} else if (has_dotgit) {
|
|
1043
|
+
if (git_path_dirname_r(wd_path, repo_path->ptr) < 0)
|
|
1044
|
+
return -1;
|
|
1045
|
+
} else {
|
|
1046
|
+
giterr_set(GITERR_REPOSITORY, "Cannot pick working directory"
|
|
1047
|
+
" for non-bare repository that isn't a '.git' directory");
|
|
837
1048
|
return -1;
|
|
1049
|
+
}
|
|
1050
|
+
|
|
1051
|
+
if (git_path_to_dir(wd_path) < 0)
|
|
1052
|
+
return -1;
|
|
1053
|
+
} else {
|
|
1054
|
+
git_buf_clear(wd_path);
|
|
838
1055
|
}
|
|
839
1056
|
|
|
840
|
-
|
|
1057
|
+
natural_wd =
|
|
1058
|
+
has_dotgit &&
|
|
1059
|
+
wd_path->size > 0 &&
|
|
1060
|
+
wd_path->size + strlen(GIT_DIR) == repo_path->size &&
|
|
1061
|
+
memcmp(repo_path->ptr, wd_path->ptr, wd_path->size) == 0;
|
|
1062
|
+
if (natural_wd)
|
|
1063
|
+
opts->flags |= GIT_REPOSITORY_INIT__NATURAL_WD;
|
|
1064
|
+
|
|
1065
|
+
/* create directories as needed / requested */
|
|
1066
|
+
|
|
1067
|
+
dirmode = pick_dir_mode(opts);
|
|
1068
|
+
|
|
1069
|
+
if ((opts->flags & GIT_REPOSITORY_INIT_MKDIR) != 0 && has_dotgit) {
|
|
1070
|
+
git_buf p = GIT_BUF_INIT;
|
|
1071
|
+
if ((error = git_path_dirname_r(&p, repo_path->ptr)) >= 0)
|
|
1072
|
+
error = git_futils_mkdir(p.ptr, NULL, dirmode, 0);
|
|
1073
|
+
git_buf_free(&p);
|
|
1074
|
+
}
|
|
1075
|
+
|
|
1076
|
+
if ((opts->flags & GIT_REPOSITORY_INIT_MKDIR) != 0 ||
|
|
1077
|
+
(opts->flags & GIT_REPOSITORY_INIT_MKPATH) != 0 ||
|
|
1078
|
+
has_dotgit)
|
|
1079
|
+
{
|
|
1080
|
+
uint32_t mkflag = GIT_MKDIR_CHMOD;
|
|
1081
|
+
if ((opts->flags & GIT_REPOSITORY_INIT_MKPATH) != 0)
|
|
1082
|
+
mkflag |= GIT_MKDIR_PATH;
|
|
1083
|
+
error = git_futils_mkdir(repo_path->ptr, NULL, dirmode, mkflag);
|
|
1084
|
+
}
|
|
1085
|
+
|
|
1086
|
+
if (wd_path->size > 0 &&
|
|
1087
|
+
!natural_wd &&
|
|
1088
|
+
((opts->flags & GIT_REPOSITORY_INIT_MKDIR) != 0 ||
|
|
1089
|
+
(opts->flags & GIT_REPOSITORY_INIT_MKPATH) != 0))
|
|
1090
|
+
error = git_futils_mkdir(wd_path->ptr, NULL, dirmode & ~S_ISGID,
|
|
1091
|
+
(opts->flags & GIT_REPOSITORY_INIT_MKPATH) ? GIT_MKDIR_PATH : 0);
|
|
1092
|
+
|
|
1093
|
+
/* prettify both directories now that they are created */
|
|
1094
|
+
|
|
1095
|
+
if (!error) {
|
|
1096
|
+
error = git_path_prettify_dir(repo_path, repo_path->ptr, NULL);
|
|
1097
|
+
|
|
1098
|
+
if (!error && wd_path->size > 0)
|
|
1099
|
+
error = git_path_prettify_dir(wd_path, wd_path->ptr, NULL);
|
|
1100
|
+
}
|
|
1101
|
+
|
|
1102
|
+
return error;
|
|
841
1103
|
}
|
|
842
1104
|
|
|
843
|
-
int
|
|
1105
|
+
static int repo_init_create_origin(git_repository *repo, const char *url)
|
|
844
1106
|
{
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
int result = -1;
|
|
1107
|
+
int error;
|
|
1108
|
+
git_remote *remote;
|
|
848
1109
|
|
|
849
|
-
|
|
1110
|
+
if (!(error = git_remote_add(&remote, repo, GIT_REMOTE_ORIGIN, url))) {
|
|
1111
|
+
error = git_remote_save(remote);
|
|
1112
|
+
git_remote_free(remote);
|
|
1113
|
+
}
|
|
850
1114
|
|
|
851
|
-
|
|
852
|
-
|
|
1115
|
+
return error;
|
|
1116
|
+
}
|
|
853
1117
|
|
|
854
|
-
|
|
1118
|
+
int git_repository_init(
|
|
1119
|
+
git_repository **repo_out, const char *path, unsigned is_bare)
|
|
1120
|
+
{
|
|
1121
|
+
git_repository_init_options opts;
|
|
855
1122
|
|
|
856
|
-
|
|
857
|
-
|
|
1123
|
+
memset(&opts, 0, sizeof(opts));
|
|
1124
|
+
opts.flags = GIT_REPOSITORY_INIT_MKPATH; /* don't love this default */
|
|
1125
|
+
if (is_bare)
|
|
1126
|
+
opts.flags |= GIT_REPOSITORY_INIT_BARE;
|
|
858
1127
|
|
|
859
|
-
|
|
860
|
-
|
|
1128
|
+
return git_repository_init_ext(repo_out, path, &opts);
|
|
1129
|
+
}
|
|
1130
|
+
|
|
1131
|
+
int git_repository_init_ext(
|
|
1132
|
+
git_repository **repo_out,
|
|
1133
|
+
const char *given_repo,
|
|
1134
|
+
git_repository_init_options *opts)
|
|
1135
|
+
{
|
|
1136
|
+
int error;
|
|
1137
|
+
git_buf repo_path = GIT_BUF_INIT, wd_path = GIT_BUF_INIT;
|
|
1138
|
+
|
|
1139
|
+
assert(repo_out && given_repo && opts);
|
|
861
1140
|
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
repo_init_createhead(repository_path.ptr) < 0) {
|
|
1141
|
+
error = repo_init_directories(&repo_path, &wd_path, given_repo, opts);
|
|
1142
|
+
if (error < 0)
|
|
865
1143
|
goto cleanup;
|
|
1144
|
+
|
|
1145
|
+
if (valid_repository_path(&repo_path)) {
|
|
1146
|
+
|
|
1147
|
+
if ((opts->flags & GIT_REPOSITORY_INIT_NO_REINIT) != 0) {
|
|
1148
|
+
giterr_set(GITERR_REPOSITORY,
|
|
1149
|
+
"Attempt to reinitialize '%s'", given_repo);
|
|
1150
|
+
error = GIT_EEXISTS;
|
|
1151
|
+
goto cleanup;
|
|
1152
|
+
}
|
|
1153
|
+
|
|
1154
|
+
opts->flags |= GIT_REPOSITORY_INIT__IS_REINIT;
|
|
1155
|
+
|
|
1156
|
+
error = repo_init_config(
|
|
1157
|
+
git_buf_cstr(&repo_path), git_buf_cstr(&wd_path), opts);
|
|
1158
|
+
|
|
1159
|
+
/* TODO: reinitialize the templates */
|
|
1160
|
+
}
|
|
1161
|
+
else {
|
|
1162
|
+
if (!(error = repo_init_structure(
|
|
1163
|
+
git_buf_cstr(&repo_path), git_buf_cstr(&wd_path), opts)) &&
|
|
1164
|
+
!(error = repo_init_config(
|
|
1165
|
+
git_buf_cstr(&repo_path), git_buf_cstr(&wd_path), opts)))
|
|
1166
|
+
error = repo_init_create_head(
|
|
1167
|
+
git_buf_cstr(&repo_path), opts->initial_head);
|
|
866
1168
|
}
|
|
1169
|
+
if (error < 0)
|
|
1170
|
+
goto cleanup;
|
|
867
1171
|
|
|
868
|
-
|
|
1172
|
+
error = git_repository_open(repo_out, git_buf_cstr(&repo_path));
|
|
1173
|
+
|
|
1174
|
+
if (!error && opts->origin_url)
|
|
1175
|
+
error = repo_init_create_origin(*repo_out, opts->origin_url);
|
|
869
1176
|
|
|
870
1177
|
cleanup:
|
|
871
|
-
git_buf_free(&
|
|
872
|
-
|
|
1178
|
+
git_buf_free(&repo_path);
|
|
1179
|
+
git_buf_free(&wd_path);
|
|
1180
|
+
|
|
1181
|
+
return error;
|
|
873
1182
|
}
|
|
874
1183
|
|
|
875
1184
|
int git_repository_head_detached(git_repository *repo)
|
|
@@ -897,7 +1206,11 @@ int git_repository_head_detached(git_repository *repo)
|
|
|
897
1206
|
|
|
898
1207
|
int git_repository_head(git_reference **head_out, git_repository *repo)
|
|
899
1208
|
{
|
|
900
|
-
|
|
1209
|
+
int error;
|
|
1210
|
+
|
|
1211
|
+
error = git_reference_lookup_resolved(head_out, repo, GIT_HEAD_FILE, -1);
|
|
1212
|
+
|
|
1213
|
+
return error == GIT_ENOTFOUND ? GIT_EORPHANEDHEAD : error;
|
|
901
1214
|
}
|
|
902
1215
|
|
|
903
1216
|
int git_repository_head_orphan(git_repository *repo)
|
|
@@ -908,7 +1221,7 @@ int git_repository_head_orphan(git_repository *repo)
|
|
|
908
1221
|
error = git_repository_head(&ref, repo);
|
|
909
1222
|
git_reference_free(ref);
|
|
910
1223
|
|
|
911
|
-
if (error ==
|
|
1224
|
+
if (error == GIT_EORPHANEDHEAD)
|
|
912
1225
|
return 1;
|
|
913
1226
|
|
|
914
1227
|
if (error < 0)
|
|
@@ -922,7 +1235,7 @@ int git_repository_is_empty(git_repository *repo)
|
|
|
922
1235
|
git_reference *head = NULL, *branch = NULL;
|
|
923
1236
|
int error;
|
|
924
1237
|
|
|
925
|
-
if (git_reference_lookup(&head, repo,
|
|
1238
|
+
if (git_reference_lookup(&head, repo, GIT_HEAD_FILE) < 0)
|
|
926
1239
|
return -1;
|
|
927
1240
|
|
|
928
1241
|
if (git_reference_type(head) != GIT_REF_SYMBOLIC) {
|
|
@@ -930,7 +1243,7 @@ int git_repository_is_empty(git_repository *repo)
|
|
|
930
1243
|
return 0;
|
|
931
1244
|
}
|
|
932
1245
|
|
|
933
|
-
if (strcmp(git_reference_target(head), "
|
|
1246
|
+
if (strcmp(git_reference_target(head), GIT_REFS_HEADS_DIR "master") != 0) {
|
|
934
1247
|
git_reference_free(head);
|
|
935
1248
|
return 0;
|
|
936
1249
|
}
|
|
@@ -965,43 +1278,6 @@ const char *git_repository_workdir(git_repository *repo)
|
|
|
965
1278
|
return repo->workdir;
|
|
966
1279
|
}
|
|
967
1280
|
|
|
968
|
-
static int write_gitlink(
|
|
969
|
-
const char *in_dir, const char *to_repo)
|
|
970
|
-
{
|
|
971
|
-
int error;
|
|
972
|
-
git_buf buf = GIT_BUF_INIT;
|
|
973
|
-
struct stat st;
|
|
974
|
-
|
|
975
|
-
if (git_path_dirname_r(&buf, to_repo) < 0 ||
|
|
976
|
-
git_path_to_dir(&buf) < 0)
|
|
977
|
-
return -1;
|
|
978
|
-
|
|
979
|
-
/* don't write gitlink to natural workdir */
|
|
980
|
-
if (git__suffixcmp(to_repo, "/" DOT_GIT "/") == 0 &&
|
|
981
|
-
strcmp(in_dir, buf.ptr) == 0)
|
|
982
|
-
return GIT_PASSTHROUGH;
|
|
983
|
-
|
|
984
|
-
if (git_buf_joinpath(&buf, in_dir, DOT_GIT) < 0)
|
|
985
|
-
return -1;
|
|
986
|
-
|
|
987
|
-
if (!p_stat(buf.ptr, &st) && !S_ISREG(st.st_mode)) {
|
|
988
|
-
giterr_set(GITERR_REPOSITORY,
|
|
989
|
-
"Cannot overwrite gitlink file into path '%s'", in_dir);
|
|
990
|
-
return GIT_EEXISTS;
|
|
991
|
-
}
|
|
992
|
-
|
|
993
|
-
git_buf_clear(&buf);
|
|
994
|
-
|
|
995
|
-
if (git_buf_printf(&buf, "%s %s", GIT_FILE_CONTENT_PREFIX, to_repo) < 0)
|
|
996
|
-
return -1;
|
|
997
|
-
|
|
998
|
-
error = repo_write_template(in_dir, true, DOT_GIT, 0644, buf.ptr);
|
|
999
|
-
|
|
1000
|
-
git_buf_free(&buf);
|
|
1001
|
-
|
|
1002
|
-
return error;
|
|
1003
|
-
}
|
|
1004
|
-
|
|
1005
1281
|
int git_repository_set_workdir(
|
|
1006
1282
|
git_repository *repo, const char *workdir, int update_gitlink)
|
|
1007
1283
|
{
|
|
@@ -1022,7 +1298,7 @@ int git_repository_set_workdir(
|
|
|
1022
1298
|
if (git_repository_config__weakptr(&config, repo) < 0)
|
|
1023
1299
|
return -1;
|
|
1024
1300
|
|
|
1025
|
-
error =
|
|
1301
|
+
error = repo_write_gitlink(path.ptr, git_repository_path(repo));
|
|
1026
1302
|
|
|
1027
1303
|
/* passthrough error means gitlink is unnecessary */
|
|
1028
1304
|
if (error == GIT_PASSTHROUGH)
|
|
@@ -1078,39 +1354,27 @@ int git_repository_message(char *buffer, size_t len, git_repository *repo)
|
|
|
1078
1354
|
{
|
|
1079
1355
|
git_buf buf = GIT_BUF_INIT, path = GIT_BUF_INIT;
|
|
1080
1356
|
struct stat st;
|
|
1081
|
-
ssize_t size;
|
|
1082
1357
|
int error;
|
|
1083
1358
|
|
|
1084
1359
|
if (git_buf_joinpath(&path, repo->path_repository, MERGE_MSG_FILE) < 0)
|
|
1085
1360
|
return -1;
|
|
1086
1361
|
|
|
1087
|
-
error = p_stat(git_buf_cstr(&path), &st)
|
|
1088
|
-
if (error < 0) {
|
|
1362
|
+
if ((error = p_stat(git_buf_cstr(&path), &st)) < 0) {
|
|
1089
1363
|
if (errno == ENOENT)
|
|
1090
1364
|
error = GIT_ENOTFOUND;
|
|
1091
|
-
|
|
1092
|
-
git_buf_free(&path);
|
|
1093
|
-
return error;
|
|
1094
1365
|
}
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
return (int)st.st_size;
|
|
1366
|
+
else if (buffer != NULL) {
|
|
1367
|
+
error = git_futils_readbuffer(&buf, git_buf_cstr(&path));
|
|
1368
|
+
git_buf_copy_cstr(buffer, len, &buf);
|
|
1099
1369
|
}
|
|
1100
1370
|
|
|
1101
|
-
if (git_futils_readbuffer(&buf, git_buf_cstr(&path)) < 0)
|
|
1102
|
-
goto on_error;
|
|
1103
|
-
|
|
1104
|
-
memcpy(buffer, git_buf_cstr(&buf), len);
|
|
1105
|
-
size = git_buf_len(&buf);
|
|
1106
|
-
|
|
1107
1371
|
git_buf_free(&path);
|
|
1108
1372
|
git_buf_free(&buf);
|
|
1109
|
-
return size;
|
|
1110
1373
|
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1374
|
+
if (!error)
|
|
1375
|
+
error = (int)st.st_size + 1; /* add 1 for NUL byte */
|
|
1376
|
+
|
|
1377
|
+
return error;
|
|
1114
1378
|
}
|
|
1115
1379
|
|
|
1116
1380
|
int git_repository_message_remove(git_repository *repo)
|
|
@@ -1126,3 +1390,154 @@ int git_repository_message_remove(git_repository *repo)
|
|
|
1126
1390
|
|
|
1127
1391
|
return error;
|
|
1128
1392
|
}
|
|
1393
|
+
|
|
1394
|
+
int git_repository_hashfile(
|
|
1395
|
+
git_oid *out,
|
|
1396
|
+
git_repository *repo,
|
|
1397
|
+
const char *path,
|
|
1398
|
+
git_otype type,
|
|
1399
|
+
const char *as_path)
|
|
1400
|
+
{
|
|
1401
|
+
int error;
|
|
1402
|
+
git_vector filters = GIT_VECTOR_INIT;
|
|
1403
|
+
git_file fd = -1;
|
|
1404
|
+
git_off_t len;
|
|
1405
|
+
git_buf full_path = GIT_BUF_INIT;
|
|
1406
|
+
|
|
1407
|
+
assert(out && path && repo); /* as_path can be NULL */
|
|
1408
|
+
|
|
1409
|
+
/* At some point, it would be nice if repo could be NULL to just
|
|
1410
|
+
* apply filter rules defined in system and global files, but for
|
|
1411
|
+
* now that is not possible because git_filters_load() needs it.
|
|
1412
|
+
*/
|
|
1413
|
+
|
|
1414
|
+
error = git_path_join_unrooted(
|
|
1415
|
+
&full_path, path, repo ? git_repository_workdir(repo) : NULL, NULL);
|
|
1416
|
+
if (error < 0)
|
|
1417
|
+
return error;
|
|
1418
|
+
|
|
1419
|
+
if (!as_path)
|
|
1420
|
+
as_path = path;
|
|
1421
|
+
|
|
1422
|
+
/* passing empty string for "as_path" indicated --no-filters */
|
|
1423
|
+
if (strlen(as_path) > 0) {
|
|
1424
|
+
error = git_filters_load(&filters, repo, as_path, GIT_FILTER_TO_ODB);
|
|
1425
|
+
if (error < 0)
|
|
1426
|
+
return error;
|
|
1427
|
+
} else {
|
|
1428
|
+
error = 0;
|
|
1429
|
+
}
|
|
1430
|
+
|
|
1431
|
+
/* at this point, error is a count of the number of loaded filters */
|
|
1432
|
+
|
|
1433
|
+
fd = git_futils_open_ro(full_path.ptr);
|
|
1434
|
+
if (fd < 0) {
|
|
1435
|
+
error = fd;
|
|
1436
|
+
goto cleanup;
|
|
1437
|
+
}
|
|
1438
|
+
|
|
1439
|
+
len = git_futils_filesize(fd);
|
|
1440
|
+
if (len < 0) {
|
|
1441
|
+
error = (int)len;
|
|
1442
|
+
goto cleanup;
|
|
1443
|
+
}
|
|
1444
|
+
|
|
1445
|
+
if (!git__is_sizet(len)) {
|
|
1446
|
+
giterr_set(GITERR_OS, "File size overflow for 32-bit systems");
|
|
1447
|
+
error = -1;
|
|
1448
|
+
goto cleanup;
|
|
1449
|
+
}
|
|
1450
|
+
|
|
1451
|
+
error = git_odb__hashfd_filtered(out, fd, (size_t)len, type, &filters);
|
|
1452
|
+
|
|
1453
|
+
cleanup:
|
|
1454
|
+
if (fd >= 0)
|
|
1455
|
+
p_close(fd);
|
|
1456
|
+
git_filters_free(&filters);
|
|
1457
|
+
git_buf_free(&full_path);
|
|
1458
|
+
|
|
1459
|
+
return error;
|
|
1460
|
+
}
|
|
1461
|
+
|
|
1462
|
+
static bool looks_like_a_branch(const char *refname)
|
|
1463
|
+
{
|
|
1464
|
+
return git__prefixcmp(refname, GIT_REFS_HEADS_DIR) == 0;
|
|
1465
|
+
}
|
|
1466
|
+
|
|
1467
|
+
int git_repository_set_head(
|
|
1468
|
+
git_repository* repo,
|
|
1469
|
+
const char* refname)
|
|
1470
|
+
{
|
|
1471
|
+
git_reference *ref,
|
|
1472
|
+
*new_head = NULL;
|
|
1473
|
+
int error;
|
|
1474
|
+
|
|
1475
|
+
assert(repo && refname);
|
|
1476
|
+
|
|
1477
|
+
error = git_reference_lookup(&ref, repo, refname);
|
|
1478
|
+
if (error < 0 && error != GIT_ENOTFOUND)
|
|
1479
|
+
return error;
|
|
1480
|
+
|
|
1481
|
+
if (!error) {
|
|
1482
|
+
if (git_reference_is_branch(ref))
|
|
1483
|
+
error = git_reference_create_symbolic(&new_head, repo, GIT_HEAD_FILE, git_reference_name(ref), 1);
|
|
1484
|
+
else
|
|
1485
|
+
error = git_repository_set_head_detached(repo, git_reference_oid(ref));
|
|
1486
|
+
} else if (looks_like_a_branch(refname))
|
|
1487
|
+
error = git_reference_create_symbolic(&new_head, repo, GIT_HEAD_FILE, refname, 1);
|
|
1488
|
+
|
|
1489
|
+
git_reference_free(ref);
|
|
1490
|
+
git_reference_free(new_head);
|
|
1491
|
+
return error;
|
|
1492
|
+
}
|
|
1493
|
+
|
|
1494
|
+
int git_repository_set_head_detached(
|
|
1495
|
+
git_repository* repo,
|
|
1496
|
+
const git_oid* commitish)
|
|
1497
|
+
{
|
|
1498
|
+
int error;
|
|
1499
|
+
git_object *object,
|
|
1500
|
+
*peeled = NULL;
|
|
1501
|
+
git_reference *new_head = NULL;
|
|
1502
|
+
|
|
1503
|
+
assert(repo && commitish);
|
|
1504
|
+
|
|
1505
|
+
if ((error = git_object_lookup(&object, repo, commitish, GIT_OBJ_ANY)) < 0)
|
|
1506
|
+
return error;
|
|
1507
|
+
|
|
1508
|
+
if ((error = git_object_peel(&peeled, object, GIT_OBJ_COMMIT)) < 0)
|
|
1509
|
+
goto cleanup;
|
|
1510
|
+
|
|
1511
|
+
error = git_reference_create_oid(&new_head, repo, GIT_HEAD_FILE, git_object_id(peeled), 1);
|
|
1512
|
+
|
|
1513
|
+
cleanup:
|
|
1514
|
+
git_object_free(object);
|
|
1515
|
+
git_object_free(peeled);
|
|
1516
|
+
git_reference_free(new_head);
|
|
1517
|
+
return error;
|
|
1518
|
+
}
|
|
1519
|
+
|
|
1520
|
+
int git_repository_detach_head(
|
|
1521
|
+
git_repository* repo)
|
|
1522
|
+
{
|
|
1523
|
+
git_reference *old_head = NULL,
|
|
1524
|
+
*new_head = NULL;
|
|
1525
|
+
git_object *object = NULL;
|
|
1526
|
+
int error;
|
|
1527
|
+
|
|
1528
|
+
assert(repo);
|
|
1529
|
+
|
|
1530
|
+
if ((error = git_repository_head(&old_head, repo)) < 0)
|
|
1531
|
+
return error;
|
|
1532
|
+
|
|
1533
|
+
if ((error = git_object_lookup(&object, repo, git_reference_oid(old_head), GIT_OBJ_COMMIT)) < 0)
|
|
1534
|
+
goto cleanup;
|
|
1535
|
+
|
|
1536
|
+
error = git_reference_create_oid(&new_head, repo, GIT_HEAD_FILE, git_reference_oid(old_head), 1);
|
|
1537
|
+
|
|
1538
|
+
cleanup:
|
|
1539
|
+
git_object_free(object);
|
|
1540
|
+
git_reference_free(old_head);
|
|
1541
|
+
git_reference_free(new_head);
|
|
1542
|
+
return error;
|
|
1543
|
+
}
|