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/reflog.c
CHANGED
@@ -372,7 +372,7 @@ int git_reflog_rename(git_reference *ref, const char *new_name)
|
|
372
372
|
goto cleanup;
|
373
373
|
|
374
374
|
if (git_path_isdir(git_buf_cstr(&new_path)) &&
|
375
|
-
(git_futils_rmdir_r(git_buf_cstr(&new_path), GIT_DIRREMOVAL_ONLY_EMPTY_DIRS) < 0))
|
375
|
+
(git_futils_rmdir_r(git_buf_cstr(&new_path), NULL, GIT_DIRREMOVAL_ONLY_EMPTY_DIRS) < 0))
|
376
376
|
goto cleanup;
|
377
377
|
|
378
378
|
if (git_futils_mkpath2file(git_buf_cstr(&new_path), GIT_REFLOG_DIR_MODE) < 0)
|
data/vendor/libgit2/src/refs.c
CHANGED
@@ -15,6 +15,7 @@
|
|
15
15
|
#include <git2/tag.h>
|
16
16
|
#include <git2/object.h>
|
17
17
|
#include <git2/oid.h>
|
18
|
+
#include <git2/branch.h>
|
18
19
|
|
19
20
|
GIT__USE_STRMAP;
|
20
21
|
|
@@ -68,11 +69,6 @@ static int reference_path_available(git_repository *repo,
|
|
68
69
|
static int reference_delete(git_reference *ref);
|
69
70
|
static int reference_lookup(git_reference *ref);
|
70
71
|
|
71
|
-
/* name normalization */
|
72
|
-
static int normalize_name(char *buffer_out, size_t out_size,
|
73
|
-
const char *name, int is_oid_ref);
|
74
|
-
|
75
|
-
|
76
72
|
void git_reference_free(git_reference *reference)
|
77
73
|
{
|
78
74
|
if (reference == NULL)
|
@@ -159,11 +155,26 @@ static int loose_parse_symbolic(git_reference *ref, git_buf *file_content)
|
|
159
155
|
|
160
156
|
static int loose_parse_oid(git_oid *oid, git_buf *file_content)
|
161
157
|
{
|
162
|
-
|
163
|
-
|
164
|
-
|
158
|
+
size_t len;
|
159
|
+
const char *str;
|
160
|
+
|
161
|
+
len = git_buf_len(file_content);
|
162
|
+
if (len < GIT_OID_HEXSZ)
|
163
|
+
goto corrupted;
|
164
|
+
|
165
|
+
/* str is guranteed to be zero-terminated */
|
166
|
+
str = git_buf_cstr(file_content);
|
167
|
+
|
168
|
+
/* If the file is longer than 40 chars, the 41st must be a space */
|
169
|
+
if (git_oid_fromstr(oid, git_buf_cstr(file_content)) < 0)
|
170
|
+
goto corrupted;
|
171
|
+
|
172
|
+
/* If the file is longer than 40 chars, the 41st must be a space */
|
173
|
+
str += GIT_OID_HEXSZ;
|
174
|
+
if (*str == '\0' || git__isspace(*str))
|
165
175
|
return 0;
|
166
176
|
|
177
|
+
corrupted:
|
167
178
|
giterr_set(GITERR_REFERENCE, "Corrupted loose reference file");
|
168
179
|
return -1;
|
169
180
|
}
|
@@ -200,8 +211,6 @@ static int loose_lookup(git_reference *ref)
|
|
200
211
|
if (!updated)
|
201
212
|
return 0;
|
202
213
|
|
203
|
-
git_buf_rtrim(&ref_file);
|
204
|
-
|
205
214
|
if (ref->flags & GIT_REF_SYMBOLIC) {
|
206
215
|
git__free(ref->target.symbolic);
|
207
216
|
ref->target.symbolic = NULL;
|
@@ -211,6 +220,7 @@ static int loose_lookup(git_reference *ref)
|
|
211
220
|
|
212
221
|
if (git__prefixcmp((const char *)(ref_file.ptr), GIT_SYMREF) == 0) {
|
213
222
|
ref->flags |= GIT_REF_SYMBOLIC;
|
223
|
+
git_buf_rtrim(&ref_file);
|
214
224
|
result = loose_parse_symbolic(ref, &ref_file);
|
215
225
|
} else {
|
216
226
|
ref->flags |= GIT_REF_OID;
|
@@ -266,14 +276,15 @@ static int loose_write(git_reference *ref)
|
|
266
276
|
if (git_buf_joinpath(&ref_path, ref->owner->path_repository, ref->name) < 0)
|
267
277
|
return -1;
|
268
278
|
|
269
|
-
/* Remove a possibly existing empty directory hierarchy
|
279
|
+
/* Remove a possibly existing empty directory hierarchy
|
270
280
|
* which name would collide with the reference name
|
271
281
|
*/
|
272
|
-
if (git_path_isdir(git_buf_cstr(&ref_path)) &&
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
282
|
+
if (git_path_isdir(git_buf_cstr(&ref_path)) &&
|
283
|
+
git_futils_rmdir_r(git_buf_cstr(&ref_path), NULL,
|
284
|
+
GIT_DIRREMOVAL_ONLY_EMPTY_DIRS) < 0) {
|
285
|
+
git_buf_free(&ref_path);
|
286
|
+
return -1;
|
287
|
+
}
|
277
288
|
|
278
289
|
if (git_filebuf_open(&file, ref_path.ptr, GIT_FILEBUF_FORCE) < 0) {
|
279
290
|
git_buf_free(&ref_path);
|
@@ -499,6 +510,10 @@ static int _dirent_loose_listall(void *_data, git_buf *full_path)
|
|
499
510
|
return 0; /* we are filtering out this reference */
|
500
511
|
}
|
501
512
|
|
513
|
+
/* Locked references aren't returned */
|
514
|
+
if (!git__suffixcmp(file_path, GIT_FILELOCK_EXTENSION))
|
515
|
+
return 0;
|
516
|
+
|
502
517
|
if (data->callback(file_path, data->callback_payload))
|
503
518
|
data->callback_error = GIT_EUSER;
|
504
519
|
|
@@ -1099,9 +1114,12 @@ int git_reference_lookup_resolved(
|
|
1099
1114
|
scan->name = git__calloc(GIT_REFNAME_MAX + 1, sizeof(char));
|
1100
1115
|
GITERR_CHECK_ALLOC(scan->name);
|
1101
1116
|
|
1102
|
-
if ((result =
|
1103
|
-
|
1104
|
-
|
1117
|
+
if ((result = git_reference__normalize_name_lax(
|
1118
|
+
scan->name,
|
1119
|
+
GIT_REFNAME_MAX,
|
1120
|
+
name)) < 0) {
|
1121
|
+
git_reference_free(scan);
|
1122
|
+
return result;
|
1105
1123
|
}
|
1106
1124
|
|
1107
1125
|
scan->target.symbolic = git__strdup(scan->name);
|
@@ -1197,12 +1215,16 @@ int git_reference_create_symbolic(
|
|
1197
1215
|
{
|
1198
1216
|
char normalized[GIT_REFNAME_MAX];
|
1199
1217
|
git_reference *ref = NULL;
|
1218
|
+
int error;
|
1200
1219
|
|
1201
|
-
if (
|
1202
|
-
|
1220
|
+
if (git_reference__normalize_name_lax(
|
1221
|
+
normalized,
|
1222
|
+
sizeof(normalized),
|
1223
|
+
name) < 0)
|
1224
|
+
return -1;
|
1203
1225
|
|
1204
|
-
if (reference_can_write(repo, normalized, NULL, force) < 0)
|
1205
|
-
return
|
1226
|
+
if ((error = reference_can_write(repo, normalized, NULL, force)) < 0)
|
1227
|
+
return error;
|
1206
1228
|
|
1207
1229
|
if (reference_alloc(&ref, repo, normalized) < 0)
|
1208
1230
|
return -1;
|
@@ -1231,14 +1253,18 @@ int git_reference_create_oid(
|
|
1231
1253
|
const git_oid *id,
|
1232
1254
|
int force)
|
1233
1255
|
{
|
1256
|
+
int error;
|
1234
1257
|
git_reference *ref = NULL;
|
1235
1258
|
char normalized[GIT_REFNAME_MAX];
|
1236
1259
|
|
1237
|
-
if (
|
1238
|
-
|
1260
|
+
if (git_reference__normalize_name_lax(
|
1261
|
+
normalized,
|
1262
|
+
sizeof(normalized),
|
1263
|
+
name) < 0)
|
1264
|
+
return -1;
|
1239
1265
|
|
1240
|
-
if (reference_can_write(repo, normalized, NULL, force) < 0)
|
1241
|
-
return
|
1266
|
+
if ((error = reference_can_write(repo, normalized, NULL, force)) < 0)
|
1267
|
+
return error;
|
1242
1268
|
|
1243
1269
|
if (reference_alloc(&ref, repo, name) < 0)
|
1244
1270
|
return -1;
|
@@ -1314,8 +1340,11 @@ int git_reference_set_target(git_reference *ref, const char *target)
|
|
1314
1340
|
return -1;
|
1315
1341
|
}
|
1316
1342
|
|
1317
|
-
if (
|
1318
|
-
|
1343
|
+
if (git_reference__normalize_name_lax(
|
1344
|
+
normalized,
|
1345
|
+
sizeof(normalized),
|
1346
|
+
target))
|
1347
|
+
return -1;
|
1319
1348
|
|
1320
1349
|
git__free(ref->target.symbolic);
|
1321
1350
|
ref->target.symbolic = git__strdup(normalized);
|
@@ -1327,24 +1356,36 @@ int git_reference_set_target(git_reference *ref, const char *target)
|
|
1327
1356
|
int git_reference_rename(git_reference *ref, const char *new_name, int force)
|
1328
1357
|
{
|
1329
1358
|
int result;
|
1359
|
+
unsigned int normalization_flags;
|
1330
1360
|
git_buf aux_path = GIT_BUF_INIT;
|
1331
1361
|
char normalized[GIT_REFNAME_MAX];
|
1362
|
+
bool should_head_be_updated = false;
|
1332
1363
|
|
1333
|
-
|
1334
|
-
|
1364
|
+
normalization_flags = ref->flags & GIT_REF_SYMBOLIC ?
|
1365
|
+
GIT_REF_FORMAT_ALLOW_ONELEVEL
|
1366
|
+
: GIT_REF_FORMAT_NORMAL;
|
1335
1367
|
|
1336
|
-
if (
|
1337
|
-
|
1338
|
-
|
1368
|
+
if (git_reference_normalize_name(
|
1369
|
+
normalized,
|
1370
|
+
sizeof(normalized),
|
1371
|
+
new_name,
|
1372
|
+
normalization_flags) < 0)
|
1373
|
+
return -1;
|
1339
1374
|
|
1340
|
-
if (reference_can_write(ref->owner, normalized, ref->name, force) < 0)
|
1341
|
-
return
|
1375
|
+
if ((result = reference_can_write(ref->owner, normalized, ref->name, force)) < 0)
|
1376
|
+
return result;
|
1342
1377
|
|
1343
1378
|
/* Initialize path now so we won't get an allocation failure once
|
1344
1379
|
* we actually start removing things. */
|
1345
1380
|
if (git_buf_joinpath(&aux_path, ref->owner->path_repository, new_name) < 0)
|
1346
1381
|
return -1;
|
1347
1382
|
|
1383
|
+
/*
|
1384
|
+
* Check if we have to update HEAD.
|
1385
|
+
*/
|
1386
|
+
if ((should_head_be_updated = git_branch_is_head(ref)) < 0)
|
1387
|
+
goto cleanup;
|
1388
|
+
|
1348
1389
|
/*
|
1349
1390
|
* Now delete the old ref and remove an possibly existing directory
|
1350
1391
|
* named `new_name`. Note that using the internal `reference_delete`
|
@@ -1369,25 +1410,13 @@ int git_reference_rename(git_reference *ref, const char *new_name, int force)
|
|
1369
1410
|
goto rollback;
|
1370
1411
|
|
1371
1412
|
/*
|
1372
|
-
*
|
1413
|
+
* Update HEAD it was poiting to the reference being renamed.
|
1373
1414
|
*/
|
1374
|
-
if (
|
1375
|
-
|
1376
|
-
"Failed to update HEAD after renaming reference");
|
1377
|
-
goto cleanup;
|
1378
|
-
}
|
1379
|
-
|
1380
|
-
head_target = git_reference_target(head);
|
1381
|
-
|
1382
|
-
if (head_target && !strcmp(head_target, ref->name)) {
|
1383
|
-
git_reference_free(head);
|
1384
|
-
head = NULL;
|
1385
|
-
|
1386
|
-
if (git_reference_create_symbolic(&head, ref->owner, "HEAD", new_name, 1) < 0) {
|
1415
|
+
if (should_head_be_updated &&
|
1416
|
+
git_repository_set_head(ref->owner, new_name) < 0) {
|
1387
1417
|
giterr_set(GITERR_REFERENCE,
|
1388
1418
|
"Failed to update HEAD after renaming reference");
|
1389
1419
|
goto cleanup;
|
1390
|
-
}
|
1391
1420
|
}
|
1392
1421
|
|
1393
1422
|
/*
|
@@ -1405,12 +1434,10 @@ int git_reference_rename(git_reference *ref, const char *new_name, int force)
|
|
1405
1434
|
/* The reference is no longer packed */
|
1406
1435
|
ref->flags &= ~GIT_REF_PACKED;
|
1407
1436
|
|
1408
|
-
git_reference_free(head);
|
1409
1437
|
git_buf_free(&aux_path);
|
1410
1438
|
return 0;
|
1411
1439
|
|
1412
1440
|
cleanup:
|
1413
|
-
git_reference_free(head);
|
1414
1441
|
git_buf_free(&aux_path);
|
1415
1442
|
return -1;
|
1416
1443
|
|
@@ -1565,112 +1592,185 @@ static int is_valid_ref_char(char ch)
|
|
1565
1592
|
}
|
1566
1593
|
}
|
1567
1594
|
|
1568
|
-
static int
|
1569
|
-
char *buffer_out,
|
1570
|
-
size_t out_size,
|
1571
|
-
const char *name,
|
1572
|
-
int is_oid_ref)
|
1595
|
+
static int ensure_segment_validity(const char *name)
|
1573
1596
|
{
|
1574
|
-
const char *
|
1575
|
-
|
1576
|
-
int contains_a_slash = 0;
|
1597
|
+
const char *current = name;
|
1598
|
+
char prev = '\0';
|
1577
1599
|
|
1578
|
-
|
1600
|
+
if (*current == '.')
|
1601
|
+
return -1; /* Refname starts with "." */
|
1579
1602
|
|
1580
|
-
|
1581
|
-
|
1582
|
-
|
1603
|
+
for (current = name; ; current++) {
|
1604
|
+
if (*current == '\0' || *current == '/')
|
1605
|
+
break;
|
1583
1606
|
|
1584
|
-
|
1585
|
-
|
1607
|
+
if (!is_valid_ref_char(*current))
|
1608
|
+
return -1; /* Illegal character in refname */
|
1586
1609
|
|
1587
|
-
|
1588
|
-
|
1589
|
-
goto invalid_name;
|
1610
|
+
if (prev == '.' && *current == '.')
|
1611
|
+
return -1; /* Refname contains ".." */
|
1590
1612
|
|
1591
|
-
|
1592
|
-
|
1593
|
-
goto invalid_name;
|
1613
|
+
if (prev == '@' && *current == '{')
|
1614
|
+
return -1; /* Refname contains "@{" */
|
1594
1615
|
|
1595
|
-
|
1596
|
-
|
1597
|
-
|
1616
|
+
prev = *current;
|
1617
|
+
}
|
1618
|
+
|
1619
|
+
return (int)(current - name);
|
1620
|
+
}
|
1598
1621
|
|
1599
|
-
|
1600
|
-
|
1622
|
+
static bool is_all_caps_and_underscore(const char *name, size_t len)
|
1623
|
+
{
|
1624
|
+
size_t i;
|
1625
|
+
char c;
|
1601
1626
|
|
1602
|
-
|
1603
|
-
if (*current == '.' && ((prev == '.') || (prev == '/')))
|
1604
|
-
goto invalid_name;
|
1627
|
+
assert(name && len > 0);
|
1605
1628
|
|
1606
|
-
|
1607
|
-
|
1608
|
-
|
1629
|
+
for (i = 0; i < len; i++)
|
1630
|
+
{
|
1631
|
+
c = name[i];
|
1632
|
+
if ((c < 'A' || c > 'Z') && c != '_')
|
1633
|
+
return false;
|
1634
|
+
}
|
1609
1635
|
|
1610
|
-
|
1611
|
-
|
1612
|
-
|
1613
|
-
|
1636
|
+
if (*name == '_' || name[len - 1] == '_')
|
1637
|
+
return false;
|
1638
|
+
|
1639
|
+
return true;
|
1640
|
+
}
|
1641
|
+
|
1642
|
+
int git_reference__normalize_name(
|
1643
|
+
git_buf *buf,
|
1644
|
+
const char *name,
|
1645
|
+
unsigned int flags)
|
1646
|
+
{
|
1647
|
+
// Inspired from https://github.com/git/git/blob/f06d47e7e0d9db709ee204ed13a8a7486149f494/refs.c#L36-100
|
1648
|
+
|
1649
|
+
char *current;
|
1650
|
+
int segment_len, segments_count = 0, error = -1;
|
1651
|
+
unsigned int process_flags;
|
1652
|
+
bool normalize = (buf != NULL);
|
1653
|
+
assert(name);
|
1654
|
+
|
1655
|
+
process_flags = flags;
|
1656
|
+
current = (char *)name;
|
1657
|
+
|
1658
|
+
if (normalize)
|
1659
|
+
git_buf_clear(buf);
|
1660
|
+
|
1661
|
+
while (true) {
|
1662
|
+
segment_len = ensure_segment_validity(current);
|
1663
|
+
if (segment_len < 0) {
|
1664
|
+
if ((process_flags & GIT_REF_FORMAT_REFSPEC_PATTERN) &&
|
1665
|
+
current[0] == '*' &&
|
1666
|
+
(current[1] == '\0' || current[1] == '/')) {
|
1667
|
+
/* Accept one wildcard as a full refname component. */
|
1668
|
+
process_flags &= ~GIT_REF_FORMAT_REFSPEC_PATTERN;
|
1669
|
+
segment_len = 1;
|
1670
|
+
} else
|
1671
|
+
goto cleanup;
|
1672
|
+
}
|
1673
|
+
|
1674
|
+
if (segment_len > 0) {
|
1675
|
+
if (normalize) {
|
1676
|
+
size_t cur_len = git_buf_len(buf);
|
1677
|
+
|
1678
|
+
git_buf_joinpath(buf, git_buf_cstr(buf), current);
|
1679
|
+
git_buf_truncate(buf,
|
1680
|
+
cur_len + segment_len + (segments_count ? 1 : 0));
|
1681
|
+
|
1682
|
+
if (git_buf_oom(buf))
|
1683
|
+
goto cleanup;
|
1614
1684
|
}
|
1685
|
+
|
1686
|
+
segments_count++;
|
1615
1687
|
}
|
1616
1688
|
|
1617
|
-
if (
|
1618
|
-
|
1689
|
+
if (current[segment_len] == '\0')
|
1690
|
+
break;
|
1619
1691
|
|
1620
|
-
|
1621
|
-
out_size--;
|
1692
|
+
current += segment_len + 1;
|
1622
1693
|
}
|
1623
1694
|
|
1624
|
-
|
1625
|
-
|
1695
|
+
/* A refname can not be empty */
|
1696
|
+
if (segment_len == 0 && segments_count == 0)
|
1697
|
+
goto cleanup;
|
1626
1698
|
|
1627
|
-
/*
|
1628
|
-
|
1629
|
-
|
1630
|
-
|
1631
|
-
|
1632
|
-
|
1633
|
-
|
1634
|
-
strcmp(name, GIT_FETCH_HEAD_FILE) != 0)
|
1635
|
-
goto invalid_name;
|
1699
|
+
/* A refname can not end with "." */
|
1700
|
+
if (current[segment_len - 1] == '.')
|
1701
|
+
goto cleanup;
|
1702
|
+
|
1703
|
+
/* A refname can not end with "/" */
|
1704
|
+
if (current[segment_len - 1] == '/')
|
1705
|
+
goto cleanup;
|
1636
1706
|
|
1637
1707
|
/* A refname can not end with ".lock" */
|
1638
1708
|
if (!git__suffixcmp(name, GIT_FILELOCK_EXTENSION))
|
1639
|
-
goto
|
1709
|
+
goto cleanup;
|
1640
1710
|
|
1641
|
-
|
1711
|
+
if ((segments_count == 1 ) && !(flags & GIT_REF_FORMAT_ALLOW_ONELEVEL))
|
1712
|
+
goto cleanup;
|
1642
1713
|
|
1643
|
-
|
1644
|
-
|
1645
|
-
|
1646
|
-
|
1647
|
-
if (is_oid_ref && !(git__prefixcmp(buffer_out_start, GIT_REFS_DIR) ||
|
1648
|
-
strcmp(buffer_out_start, GIT_HEAD_FILE)))
|
1649
|
-
goto invalid_name;
|
1714
|
+
if ((segments_count == 1 ) &&
|
1715
|
+
!(is_all_caps_and_underscore(name, (size_t)segment_len) ||
|
1716
|
+
((flags & GIT_REF_FORMAT_REFSPEC_PATTERN) && !strcmp("*", name))))
|
1717
|
+
goto cleanup;
|
1650
1718
|
|
1651
|
-
|
1719
|
+
if ((segments_count > 1)
|
1720
|
+
&& (is_all_caps_and_underscore(name, strchr(name, '/') - name)))
|
1721
|
+
goto cleanup;
|
1652
1722
|
|
1653
|
-
|
1654
|
-
|
1655
|
-
|
1723
|
+
error = 0;
|
1724
|
+
|
1725
|
+
cleanup:
|
1726
|
+
if (error)
|
1727
|
+
giterr_set(
|
1728
|
+
GITERR_REFERENCE,
|
1729
|
+
"The given reference name '%s' is not valid", name);
|
1730
|
+
|
1731
|
+
return error;
|
1656
1732
|
}
|
1657
1733
|
|
1658
|
-
int
|
1734
|
+
int git_reference_normalize_name(
|
1659
1735
|
char *buffer_out,
|
1660
|
-
size_t
|
1661
|
-
const char *name
|
1736
|
+
size_t buffer_size,
|
1737
|
+
const char *name,
|
1738
|
+
unsigned int flags)
|
1662
1739
|
{
|
1663
|
-
|
1740
|
+
git_buf buf = GIT_BUF_INIT;
|
1741
|
+
int error;
|
1742
|
+
|
1743
|
+
if ((error = git_reference__normalize_name(&buf, name, flags)) < 0)
|
1744
|
+
goto cleanup;
|
1745
|
+
|
1746
|
+
if (git_buf_len(&buf) > buffer_size - 1) {
|
1747
|
+
giterr_set(
|
1748
|
+
GITERR_REFERENCE,
|
1749
|
+
"The provided buffer is too short to hold the normalization of '%s'", name);
|
1750
|
+
error = GIT_EBUFS;
|
1751
|
+
goto cleanup;
|
1752
|
+
}
|
1753
|
+
|
1754
|
+
git_buf_copy_cstr(buffer_out, buffer_size, &buf);
|
1755
|
+
|
1756
|
+
error = 0;
|
1757
|
+
|
1758
|
+
cleanup:
|
1759
|
+
git_buf_free(&buf);
|
1760
|
+
return error;
|
1664
1761
|
}
|
1665
1762
|
|
1666
|
-
int
|
1763
|
+
int git_reference__normalize_name_lax(
|
1667
1764
|
char *buffer_out,
|
1668
1765
|
size_t out_size,
|
1669
1766
|
const char *name)
|
1670
1767
|
{
|
1671
|
-
return
|
1768
|
+
return git_reference_normalize_name(
|
1769
|
+
buffer_out,
|
1770
|
+
out_size,
|
1771
|
+
name,
|
1772
|
+
GIT_REF_FORMAT_ALLOW_ONELEVEL);
|
1672
1773
|
}
|
1673
|
-
|
1674
1774
|
#define GIT_REF_TYPEMASK (GIT_REF_OID | GIT_REF_SYMBOLIC)
|
1675
1775
|
|
1676
1776
|
int git_reference_cmp(git_reference *ref1, git_reference *ref2)
|
@@ -1804,6 +1904,74 @@ int git_reference_has_log(
|
|
1804
1904
|
int git_reference_is_branch(git_reference *ref)
|
1805
1905
|
{
|
1806
1906
|
assert(ref);
|
1807
|
-
|
1808
1907
|
return git__prefixcmp(ref->name, GIT_REFS_HEADS_DIR) == 0;
|
1809
1908
|
}
|
1909
|
+
|
1910
|
+
int git_reference_is_remote(git_reference *ref)
|
1911
|
+
{
|
1912
|
+
assert(ref);
|
1913
|
+
return git__prefixcmp(ref->name, GIT_REFS_REMOTES_DIR) == 0;
|
1914
|
+
}
|
1915
|
+
|
1916
|
+
static int peel_error(int error, git_reference *ref, const char* msg)
|
1917
|
+
{
|
1918
|
+
giterr_set(
|
1919
|
+
GITERR_INVALID,
|
1920
|
+
"The reference '%s' cannot be peeled - %s", git_reference_name(ref), msg);
|
1921
|
+
return error;
|
1922
|
+
}
|
1923
|
+
|
1924
|
+
static int reference_target(git_object **object, git_reference *ref)
|
1925
|
+
{
|
1926
|
+
const git_oid *oid;
|
1927
|
+
|
1928
|
+
oid = git_reference_oid(ref);
|
1929
|
+
|
1930
|
+
return git_object_lookup(object, git_reference_owner(ref), oid, GIT_OBJ_ANY);
|
1931
|
+
}
|
1932
|
+
|
1933
|
+
int git_reference_peel(
|
1934
|
+
git_object **peeled,
|
1935
|
+
git_reference *ref,
|
1936
|
+
git_otype target_type)
|
1937
|
+
{
|
1938
|
+
git_reference *resolved = NULL;
|
1939
|
+
git_object *target = NULL;
|
1940
|
+
int error;
|
1941
|
+
|
1942
|
+
assert(ref);
|
1943
|
+
|
1944
|
+
if ((error = git_reference_resolve(&resolved, ref)) < 0)
|
1945
|
+
return peel_error(error, ref, "Cannot resolve reference");
|
1946
|
+
|
1947
|
+
if ((error = reference_target(&target, resolved)) < 0) {
|
1948
|
+
peel_error(error, ref, "Cannot retrieve reference target");
|
1949
|
+
goto cleanup;
|
1950
|
+
}
|
1951
|
+
|
1952
|
+
if (target_type == GIT_OBJ_ANY && git_object_type(target) != GIT_OBJ_TAG)
|
1953
|
+
error = git_object__dup(peeled, target);
|
1954
|
+
else
|
1955
|
+
error = git_object_peel(peeled, target, target_type);
|
1956
|
+
|
1957
|
+
cleanup:
|
1958
|
+
git_object_free(target);
|
1959
|
+
git_reference_free(resolved);
|
1960
|
+
return error;
|
1961
|
+
}
|
1962
|
+
|
1963
|
+
int git_reference__is_valid_name(
|
1964
|
+
const char *refname,
|
1965
|
+
unsigned int flags)
|
1966
|
+
{
|
1967
|
+
giterr_clear();
|
1968
|
+
return git_reference__normalize_name(NULL, refname, flags) == 0;
|
1969
|
+
}
|
1970
|
+
|
1971
|
+
int git_reference_is_valid_name(
|
1972
|
+
const char *refname)
|
1973
|
+
{
|
1974
|
+
return git_reference__is_valid_name(
|
1975
|
+
refname,
|
1976
|
+
GIT_REF_FORMAT_ALLOW_ONELEVEL);
|
1977
|
+
}
|