rugged 0.17.0.b6 → 0.17.0.b7
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
}
|