2 * Copyright (C) the libgit2 contributors. All rights reserved.
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.
10 #include "repository.h"
18 #include <git2/object.h>
20 #include <git2/branch.h>
21 #include <git2/refs.h>
22 #include <git2/refdb.h>
23 #include <git2/sys/refs.h>
24 #include <git2/signature.h>
25 #include <git2/commit.h>
29 #define DEFAULT_NESTING_LEVEL 5
30 #define MAX_NESTING_LEVEL 10
33 GIT_PACKREF_HAS_PEEL
= 1,
34 GIT_PACKREF_WAS_LOOSE
= 2
37 static git_reference
*alloc_ref(const char *name
)
39 git_reference
*ref
= NULL
;
40 size_t namelen
= strlen(name
), reflen
;
42 if (!GIT_ADD_SIZET_OVERFLOW(&reflen
, sizeof(git_reference
), namelen
) &&
43 !GIT_ADD_SIZET_OVERFLOW(&reflen
, reflen
, 1) &&
44 (ref
= git__calloc(1, reflen
)) != NULL
)
45 memcpy(ref
->name
, name
, namelen
+ 1);
50 git_reference
*git_reference__alloc_symbolic(
51 const char *name
, const char *target
)
55 assert(name
&& target
);
57 ref
= alloc_ref(name
);
61 ref
->type
= GIT_REF_SYMBOLIC
;
63 if ((ref
->target
.symbolic
= git__strdup(target
)) == NULL
) {
71 git_reference
*git_reference__alloc(
80 ref
= alloc_ref(name
);
84 ref
->type
= GIT_REF_OID
;
85 git_oid_cpy(&ref
->target
.oid
, oid
);
88 git_oid_cpy(&ref
->peel
, peel
);
93 git_reference
*git_reference__set_name(
94 git_reference
*ref
, const char *name
)
96 size_t namelen
= strlen(name
);
98 git_reference
*rewrite
= NULL
;
100 if (!GIT_ADD_SIZET_OVERFLOW(&reflen
, sizeof(git_reference
), namelen
) &&
101 !GIT_ADD_SIZET_OVERFLOW(&reflen
, reflen
, 1) &&
102 (rewrite
= git__realloc(ref
, reflen
)) != NULL
)
103 memcpy(rewrite
->name
, name
, namelen
+ 1);
108 void git_reference_free(git_reference
*reference
)
110 if (reference
== NULL
)
113 if (reference
->type
== GIT_REF_SYMBOLIC
)
114 git__free(reference
->target
.symbolic
);
117 GIT_REFCOUNT_DEC(reference
->db
, git_refdb__free
);
119 git__free(reference
);
122 int git_reference_delete(git_reference
*ref
)
124 const git_oid
*old_id
= NULL
;
125 const char *old_target
= NULL
;
127 if (ref
->type
== GIT_REF_OID
)
128 old_id
= &ref
->target
.oid
;
130 old_target
= ref
->target
.symbolic
;
132 return git_refdb_delete(ref
->db
, ref
->name
, old_id
, old_target
);
135 int git_reference_remove(git_repository
*repo
, const char *name
)
140 if ((error
= git_repository_refdb__weakptr(&db
, repo
)) < 0)
143 return git_refdb_delete(db
, name
, NULL
, NULL
);
146 int git_reference_lookup(git_reference
**ref_out
,
147 git_repository
*repo
, const char *name
)
149 return git_reference_lookup_resolved(ref_out
, repo
, name
, 0);
152 int git_reference_name_to_id(
153 git_oid
*out
, git_repository
*repo
, const char *name
)
158 if ((error
= git_reference_lookup_resolved(&ref
, repo
, name
, -1)) < 0)
161 git_oid_cpy(out
, git_reference_target(ref
));
162 git_reference_free(ref
);
166 static int reference_normalize_for_repo(
168 git_repository
*repo
,
172 unsigned int flags
= GIT_REF_FORMAT_ALLOW_ONELEVEL
;
174 if (!git_repository__cvar(&precompose
, repo
, GIT_CVAR_PRECOMPOSE
) &&
176 flags
|= GIT_REF_FORMAT__PRECOMPOSE_UNICODE
;
178 return git_reference_normalize_name(out
, GIT_REFNAME_MAX
, name
, flags
);
181 int git_reference_lookup_resolved(
182 git_reference
**ref_out
,
183 git_repository
*repo
,
187 git_refname_t scan_name
;
189 int error
= 0, nesting
;
190 git_reference
*ref
= NULL
;
193 assert(ref_out
&& repo
&& name
);
197 if (max_nesting
> MAX_NESTING_LEVEL
)
198 max_nesting
= MAX_NESTING_LEVEL
;
199 else if (max_nesting
< 0)
200 max_nesting
= DEFAULT_NESTING_LEVEL
;
202 scan_type
= GIT_REF_SYMBOLIC
;
204 if ((error
= reference_normalize_for_repo(scan_name
, repo
, name
)) < 0)
207 if ((error
= git_repository_refdb__weakptr(&refdb
, repo
)) < 0)
210 for (nesting
= max_nesting
;
211 nesting
>= 0 && scan_type
== GIT_REF_SYMBOLIC
;
214 if (nesting
!= max_nesting
) {
215 strncpy(scan_name
, ref
->target
.symbolic
, sizeof(scan_name
));
216 git_reference_free(ref
);
219 if ((error
= git_refdb_lookup(&ref
, refdb
, scan_name
)) < 0)
222 scan_type
= ref
->type
;
225 if (scan_type
!= GIT_REF_OID
&& max_nesting
!= 0) {
226 giterr_set(GITERR_REFERENCE
,
227 "Cannot resolve reference (>%u levels deep)", max_nesting
);
228 git_reference_free(ref
);
236 int git_reference_dwim(git_reference
**out
, git_repository
*repo
, const char *refname
)
239 bool fallbackmode
= true, foundvalid
= false;
241 git_buf refnamebuf
= GIT_BUF_INIT
, name
= GIT_BUF_INIT
;
243 static const char* formatters
[] = {
246 GIT_REFS_TAGS_DIR
"%s",
247 GIT_REFS_HEADS_DIR
"%s",
248 GIT_REFS_REMOTES_DIR
"%s",
249 GIT_REFS_REMOTES_DIR
"%s/" GIT_HEAD_FILE
,
254 git_buf_puts(&name
, refname
);
256 git_buf_puts(&name
, GIT_HEAD_FILE
);
257 fallbackmode
= false;
260 for (i
= 0; formatters
[i
] && (fallbackmode
|| i
== 0); i
++) {
262 git_buf_clear(&refnamebuf
);
264 if ((error
= git_buf_printf(&refnamebuf
, formatters
[i
], git_buf_cstr(&name
))) < 0)
267 if (!git_reference_is_valid_name(git_buf_cstr(&refnamebuf
))) {
268 error
= GIT_EINVALIDSPEC
;
273 error
= git_reference_lookup_resolved(&ref
, repo
, git_buf_cstr(&refnamebuf
), -1);
281 if (error
!= GIT_ENOTFOUND
)
286 if (error
&& !foundvalid
) {
287 /* never found a valid reference name */
288 giterr_set(GITERR_REFERENCE
,
289 "Could not use '%s' as valid reference name", git_buf_cstr(&name
));
293 git_buf_free(&refnamebuf
);
300 git_ref_t
git_reference_type(const git_reference
*ref
)
306 const char *git_reference_name(const git_reference
*ref
)
312 git_repository
*git_reference_owner(const git_reference
*ref
)
315 return ref
->db
->repo
;
318 const git_oid
*git_reference_target(const git_reference
*ref
)
322 if (ref
->type
!= GIT_REF_OID
)
325 return &ref
->target
.oid
;
328 const git_oid
*git_reference_target_peel(const git_reference
*ref
)
332 if (ref
->type
!= GIT_REF_OID
|| git_oid_iszero(&ref
->peel
))
338 const char *git_reference_symbolic_target(const git_reference
*ref
)
342 if (ref
->type
!= GIT_REF_SYMBOLIC
)
345 return ref
->target
.symbolic
;
348 static int reference__create(
349 git_reference
**ref_out
,
350 git_repository
*repo
,
353 const char *symbolic
,
355 const git_signature
*signature
,
356 const char *log_message
,
357 const git_oid
*old_id
,
358 const char *old_target
)
360 git_refname_t normalized
;
362 git_reference
*ref
= NULL
;
365 assert(repo
&& name
);
366 assert(symbolic
|| signature
);
371 error
= reference_normalize_for_repo(normalized
, repo
, name
);
375 error
= git_repository_refdb__weakptr(&refdb
, repo
);
382 assert(symbolic
== NULL
);
384 /* Sanity check the reference being created - target must exist. */
385 if ((error
= git_repository_odb__weakptr(&odb
, repo
)) < 0)
388 if (!git_odb_exists(odb
, oid
)) {
389 giterr_set(GITERR_REFERENCE
,
390 "Target OID for the reference doesn't exist on the repository");
394 ref
= git_reference__alloc(normalized
, oid
, NULL
);
396 git_refname_t normalized_target
;
398 if ((error
= reference_normalize_for_repo(normalized_target
, repo
, symbolic
)) < 0)
401 ref
= git_reference__alloc_symbolic(normalized
, normalized_target
);
404 GITERR_CHECK_ALLOC(ref
);
406 if ((error
= git_refdb_write(refdb
, ref
, force
, signature
, log_message
, old_id
, old_target
)) < 0) {
407 git_reference_free(ref
);
412 git_reference_free(ref
);
419 int configured_ident(git_signature
**out
, const git_repository
*repo
)
421 if (repo
->ident_name
&& repo
->ident_email
)
422 return git_signature_now(out
, repo
->ident_name
, repo
->ident_email
);
424 /* if not configured let us fall-through to the next method */
428 int git_reference__log_signature(git_signature
**out
, git_repository
*repo
)
433 if(((error
= configured_ident(&who
, repo
)) < 0) &&
434 ((error
= git_signature_default(&who
, repo
)) < 0) &&
435 ((error
= git_signature_now(&who
, "unknown", "unknown")) < 0))
442 int git_reference_create_matching(
443 git_reference
**ref_out
,
444 git_repository
*repo
,
448 const git_oid
*old_id
,
449 const char *log_message
)
453 git_signature
*who
= NULL
;
457 if ((error
= git_reference__log_signature(&who
, repo
)) < 0)
460 error
= reference__create(
461 ref_out
, repo
, name
, id
, NULL
, force
, who
, log_message
, old_id
, NULL
);
463 git_signature_free(who
);
467 int git_reference_create(
468 git_reference
**ref_out
,
469 git_repository
*repo
,
473 const char *log_message
)
475 return git_reference_create_matching(ref_out
, repo
, name
, id
, force
, NULL
, log_message
);
478 int git_reference_symbolic_create_matching(
479 git_reference
**ref_out
,
480 git_repository
*repo
,
484 const char *old_target
,
485 const char *log_message
)
488 git_signature
*who
= NULL
;
492 if ((error
= git_reference__log_signature(&who
, repo
)) < 0)
495 error
= reference__create(
496 ref_out
, repo
, name
, NULL
, target
, force
, who
, log_message
, NULL
, old_target
);
498 git_signature_free(who
);
502 int git_reference_symbolic_create(
503 git_reference
**ref_out
,
504 git_repository
*repo
,
508 const char *log_message
)
510 return git_reference_symbolic_create_matching(ref_out
, repo
, name
, target
, force
, NULL
, log_message
);
513 static int ensure_is_an_updatable_direct_reference(git_reference
*ref
)
515 if (ref
->type
== GIT_REF_OID
)
518 giterr_set(GITERR_REFERENCE
, "Cannot set OID on symbolic reference");
522 int git_reference_set_target(
526 const char *log_message
)
529 git_repository
*repo
;
531 assert(out
&& ref
&& id
);
533 repo
= ref
->db
->repo
;
535 if ((error
= ensure_is_an_updatable_direct_reference(ref
)) < 0)
538 return git_reference_create_matching(out
, repo
, ref
->name
, id
, 1, &ref
->target
.oid
, log_message
);
541 static int ensure_is_an_updatable_symbolic_reference(git_reference
*ref
)
543 if (ref
->type
== GIT_REF_SYMBOLIC
)
546 giterr_set(GITERR_REFERENCE
, "Cannot set symbolic target on a direct reference");
550 int git_reference_symbolic_set_target(
554 const char *log_message
)
558 assert(out
&& ref
&& target
);
560 if ((error
= ensure_is_an_updatable_symbolic_reference(ref
)) < 0)
563 return git_reference_symbolic_create_matching(
564 out
, ref
->db
->repo
, ref
->name
, target
, 1, ref
->target
.symbolic
, log_message
);
567 static int reference__rename(git_reference
**out
, git_reference
*ref
, const char *new_name
, int force
,
568 const git_signature
*signature
, const char *message
)
570 git_refname_t normalized
;
571 bool should_head_be_updated
= false;
574 assert(ref
&& new_name
&& signature
);
576 if ((error
= reference_normalize_for_repo(
577 normalized
, git_reference_owner(ref
), new_name
)) < 0)
581 /* Check if we have to update HEAD. */
582 if ((error
= git_branch_is_head(ref
)) < 0)
585 should_head_be_updated
= (error
> 0);
587 if ((error
= git_refdb_rename(out
, ref
->db
, ref
->name
, normalized
, force
, signature
, message
)) < 0)
590 /* Update HEAD it was pointing to the reference being renamed */
591 if (should_head_be_updated
&&
592 (error
= git_repository_set_head(ref
->db
->repo
, normalized
)) < 0) {
593 giterr_set(GITERR_REFERENCE
, "Failed to update HEAD after renaming reference");
601 int git_reference_rename(
604 const char *new_name
,
606 const char *log_message
)
611 if ((error
= git_reference__log_signature(&who
, ref
->db
->repo
)) < 0)
614 error
= reference__rename(out
, ref
, new_name
, force
, who
, log_message
);
615 git_signature_free(who
);
620 int git_reference_resolve(git_reference
**ref_out
, const git_reference
*ref
)
622 switch (git_reference_type(ref
)) {
624 return git_reference_lookup(ref_out
, ref
->db
->repo
, ref
->name
);
626 case GIT_REF_SYMBOLIC
:
627 return git_reference_lookup_resolved(ref_out
, ref
->db
->repo
, ref
->target
.symbolic
, -1);
630 giterr_set(GITERR_REFERENCE
, "Invalid reference");
635 int git_reference_foreach(
636 git_repository
*repo
,
637 git_reference_foreach_cb callback
,
640 git_reference_iterator
*iter
;
644 if ((error
= git_reference_iterator_new(&iter
, repo
)) < 0)
647 while (!(error
= git_reference_next(&ref
, iter
))) {
648 if ((error
= callback(ref
, payload
)) != 0) {
649 giterr_set_after_callback(error
);
654 if (error
== GIT_ITEROVER
)
657 git_reference_iterator_free(iter
);
661 int git_reference_foreach_name(
662 git_repository
*repo
,
663 git_reference_foreach_name_cb callback
,
666 git_reference_iterator
*iter
;
670 if ((error
= git_reference_iterator_new(&iter
, repo
)) < 0)
673 while (!(error
= git_reference_next_name(&refname
, iter
))) {
674 if ((error
= callback(refname
, payload
)) != 0) {
675 giterr_set_after_callback(error
);
680 if (error
== GIT_ITEROVER
)
683 git_reference_iterator_free(iter
);
687 int git_reference_foreach_glob(
688 git_repository
*repo
,
690 git_reference_foreach_name_cb callback
,
693 git_reference_iterator
*iter
;
697 if ((error
= git_reference_iterator_glob_new(&iter
, repo
, glob
)) < 0)
700 while (!(error
= git_reference_next_name(&refname
, iter
))) {
701 if ((error
= callback(refname
, payload
)) != 0) {
702 giterr_set_after_callback(error
);
707 if (error
== GIT_ITEROVER
)
710 git_reference_iterator_free(iter
);
714 int git_reference_iterator_new(git_reference_iterator
**out
, git_repository
*repo
)
718 if (git_repository_refdb__weakptr(&refdb
, repo
) < 0)
721 return git_refdb_iterator(out
, refdb
, NULL
);
724 int git_reference_iterator_glob_new(
725 git_reference_iterator
**out
, git_repository
*repo
, const char *glob
)
729 if (git_repository_refdb__weakptr(&refdb
, repo
) < 0)
732 return git_refdb_iterator(out
, refdb
, glob
);
735 int git_reference_next(git_reference
**out
, git_reference_iterator
*iter
)
737 return git_refdb_iterator_next(out
, iter
);
740 int git_reference_next_name(const char **out
, git_reference_iterator
*iter
)
742 return git_refdb_iterator_next_name(out
, iter
);
745 void git_reference_iterator_free(git_reference_iterator
*iter
)
750 git_refdb_iterator_free(iter
);
753 static int cb__reflist_add(const char *ref
, void *data
)
755 char *name
= git__strdup(ref
);
756 GITERR_CHECK_ALLOC(name
);
757 return git_vector_insert((git_vector
*)data
, name
);
760 int git_reference_list(
762 git_repository
*repo
)
766 assert(array
&& repo
);
768 array
->strings
= NULL
;
771 if (git_vector_init(&ref_list
, 8, NULL
) < 0)
774 if (git_reference_foreach_name(
775 repo
, &cb__reflist_add
, (void *)&ref_list
) < 0) {
776 git_vector_free(&ref_list
);
780 array
->strings
= (char **)git_vector_detach(&array
->count
, NULL
, &ref_list
);
785 static int is_valid_ref_char(char ch
)
787 if ((unsigned) ch
<= ' ')
804 static int ensure_segment_validity(const char *name
)
806 const char *current
= name
;
808 const int lock_len
= (int)strlen(GIT_FILELOCK_EXTENSION
);
812 return -1; /* Refname starts with "." */
814 for (current
= name
; ; current
++) {
815 if (*current
== '\0' || *current
== '/')
818 if (!is_valid_ref_char(*current
))
819 return -1; /* Illegal character in refname */
821 if (prev
== '.' && *current
== '.')
822 return -1; /* Refname contains ".." */
824 if (prev
== '@' && *current
== '{')
825 return -1; /* Refname contains "@{" */
830 segment_len
= (int)(current
- name
);
832 /* A refname component can not end with ".lock" */
833 if (segment_len
>= lock_len
&&
834 !memcmp(current
- lock_len
, GIT_FILELOCK_EXTENSION
, lock_len
))
840 static bool is_all_caps_and_underscore(const char *name
, size_t len
)
845 assert(name
&& len
> 0);
847 for (i
= 0; i
< len
; i
++)
850 if ((c
< 'A' || c
> 'Z') && c
!= '_')
854 if (*name
== '_' || name
[len
- 1] == '_')
860 /* Inspired from https://github.com/git/git/blob/f06d47e7e0d9db709ee204ed13a8a7486149f494/refs.c#L36-100 */
861 int git_reference__normalize_name(
867 int segment_len
, segments_count
= 0, error
= GIT_EINVALIDSPEC
;
868 unsigned int process_flags
;
869 bool normalize
= (buf
!= NULL
);
872 git_path_iconv_t ic
= GIT_PATH_ICONV_INIT
;
877 process_flags
= flags
;
878 current
= (char *)name
;
887 if ((flags
& GIT_REF_FORMAT__PRECOMPOSE_UNICODE
) != 0) {
888 size_t namelen
= strlen(current
);
889 if ((error
= git_path_iconv_init_precompose(&ic
)) < 0 ||
890 (error
= git_path_iconv(&ic
, ¤t
, &namelen
)) < 0)
892 error
= GIT_EINVALIDSPEC
;
897 segment_len
= ensure_segment_validity(current
);
898 if (segment_len
< 0) {
899 if ((process_flags
& GIT_REF_FORMAT_REFSPEC_PATTERN
) &&
901 (current
[1] == '\0' || current
[1] == '/')) {
902 /* Accept one wildcard as a full refname component. */
903 process_flags
&= ~GIT_REF_FORMAT_REFSPEC_PATTERN
;
909 if (segment_len
> 0) {
911 size_t cur_len
= git_buf_len(buf
);
913 git_buf_joinpath(buf
, git_buf_cstr(buf
), current
);
914 git_buf_truncate(buf
,
915 cur_len
+ segment_len
+ (segments_count
? 1 : 0));
917 if (git_buf_oom(buf
)) {
926 /* No empty segment is allowed when not normalizing */
927 if (segment_len
== 0 && !normalize
)
930 if (current
[segment_len
] == '\0')
933 current
+= segment_len
+ 1;
936 /* A refname can not be empty */
937 if (segment_len
== 0 && segments_count
== 0)
940 /* A refname can not end with "." */
941 if (current
[segment_len
- 1] == '.')
944 /* A refname can not end with "/" */
945 if (current
[segment_len
- 1] == '/')
948 if ((segments_count
== 1 ) && !(flags
& GIT_REF_FORMAT_ALLOW_ONELEVEL
))
951 if ((segments_count
== 1 ) &&
952 !(flags
& GIT_REF_FORMAT_REFSPEC_SHORTHAND
) &&
953 !(is_all_caps_and_underscore(name
, (size_t)segment_len
) ||
954 ((flags
& GIT_REF_FORMAT_REFSPEC_PATTERN
) && !strcmp("*", name
))))
957 if ((segments_count
> 1)
958 && (is_all_caps_and_underscore(name
, strchr(name
, '/') - name
)))
964 if (error
== GIT_EINVALIDSPEC
)
967 "The given reference name '%s' is not valid", name
);
969 if (error
&& normalize
)
973 git_path_iconv_clear(&ic
);
979 int git_reference_normalize_name(
985 git_buf buf
= GIT_BUF_INIT
;
988 if ((error
= git_reference__normalize_name(&buf
, name
, flags
)) < 0)
991 if (git_buf_len(&buf
) > buffer_size
- 1) {
994 "The provided buffer is too short to hold the normalization of '%s'", name
);
999 git_buf_copy_cstr(buffer_out
, buffer_size
, &buf
);
1008 #define GIT_REF_TYPEMASK (GIT_REF_OID | GIT_REF_SYMBOLIC)
1010 int git_reference_cmp(
1011 const git_reference
*ref1
,
1012 const git_reference
*ref2
)
1014 git_ref_t type1
, type2
;
1015 assert(ref1
&& ref2
);
1017 type1
= git_reference_type(ref1
);
1018 type2
= git_reference_type(ref2
);
1020 /* let's put symbolic refs before OIDs */
1022 return (type1
== GIT_REF_SYMBOLIC
) ? -1 : 1;
1024 if (type1
== GIT_REF_SYMBOLIC
)
1025 return strcmp(ref1
->target
.symbolic
, ref2
->target
.symbolic
);
1027 return git_oid__cmp(&ref1
->target
.oid
, &ref2
->target
.oid
);
1031 * Get the end of a chain of references. If the final one is not
1032 * found, we return the reference just before that.
1034 static int get_terminal(git_reference
**out
, git_repository
*repo
, const char *ref_name
, int nesting
)
1039 if (nesting
> MAX_NESTING_LEVEL
) {
1040 giterr_set(GITERR_REFERENCE
, "Reference chain too deep (%d)", nesting
);
1041 return GIT_ENOTFOUND
;
1044 /* set to NULL to let the caller know that they're at the end of the chain */
1045 if ((error
= git_reference_lookup(&ref
, repo
, ref_name
)) < 0) {
1050 if (git_reference_type(ref
) == GIT_REF_OID
) {
1054 error
= get_terminal(out
, repo
, git_reference_symbolic_target(ref
), nesting
+ 1);
1055 if (error
== GIT_ENOTFOUND
&& !*out
)
1058 git_reference_free(ref
);
1065 * Starting with the reference given by `ref_name`, follows symbolic
1066 * references until a direct reference is found and updated the OID
1067 * on that direct reference to `oid`.
1069 int git_reference__update_terminal(
1070 git_repository
*repo
,
1071 const char *ref_name
,
1073 const git_signature
*sig
,
1074 const char *log_message
)
1076 git_reference
*ref
= NULL
, *ref2
= NULL
;
1077 git_signature
*who
= NULL
;
1078 const git_signature
*to_use
;
1081 if (!sig
&& (error
= git_reference__log_signature(&who
, repo
)) < 0)
1084 to_use
= sig
? sig
: who
;
1085 error
= get_terminal(&ref
, repo
, ref_name
, 0);
1087 /* found a dangling symref */
1088 if (error
== GIT_ENOTFOUND
&& ref
) {
1089 assert(git_reference_type(ref
) == GIT_REF_SYMBOLIC
);
1091 error
= reference__create(&ref2
, repo
, ref
->target
.symbolic
, oid
, NULL
, 0, to_use
,
1092 log_message
, NULL
, NULL
);
1093 } else if (error
== GIT_ENOTFOUND
) {
1095 error
= reference__create(&ref2
, repo
, ref_name
, oid
, NULL
, 0, to_use
,
1096 log_message
, NULL
, NULL
);
1097 } else if (error
== 0) {
1098 assert(git_reference_type(ref
) == GIT_REF_OID
);
1099 error
= reference__create(&ref2
, repo
, ref
->name
, oid
, NULL
, 1, to_use
,
1100 log_message
, &ref
->target
.oid
, NULL
);
1103 git_reference_free(ref2
);
1104 git_reference_free(ref
);
1105 git_signature_free(who
);
1109 int git_reference__update_for_commit(
1110 git_repository
*repo
,
1112 const char *ref_name
,
1114 const char *operation
)
1116 git_reference
*ref_new
= NULL
;
1117 git_commit
*commit
= NULL
;
1118 git_buf reflog_msg
= GIT_BUF_INIT
;
1119 const git_signature
*who
;
1122 if ((error
= git_commit_lookup(&commit
, repo
, id
)) < 0 ||
1123 (error
= git_buf_printf(&reflog_msg
, "%s%s: %s",
1124 operation
? operation
: "commit",
1125 git_commit_parentcount(commit
) == 0 ? " (initial)" : "",
1126 git_commit_summary(commit
))) < 0)
1129 who
= git_commit_committer(commit
);
1132 if ((error
= ensure_is_an_updatable_direct_reference(ref
)) < 0)
1135 error
= reference__create(&ref_new
, repo
, ref
->name
, id
, NULL
, 1, who
,
1136 git_buf_cstr(&reflog_msg
), &ref
->target
.oid
, NULL
);
1139 error
= git_reference__update_terminal(
1140 repo
, ref_name
, id
, who
, git_buf_cstr(&reflog_msg
));
1143 git_reference_free(ref_new
);
1144 git_buf_free(&reflog_msg
);
1145 git_commit_free(commit
);
1149 int git_reference_has_log(git_repository
*repo
, const char *refname
)
1154 assert(repo
&& refname
);
1156 if ((error
= git_repository_refdb__weakptr(&refdb
, repo
)) < 0)
1159 return git_refdb_has_log(refdb
, refname
);
1162 int git_reference_ensure_log(git_repository
*repo
, const char *refname
)
1167 assert(repo
&& refname
);
1169 if ((error
= git_repository_refdb__weakptr(&refdb
, repo
)) < 0)
1172 return git_refdb_ensure_log(refdb
, refname
);
1175 int git_reference__is_branch(const char *ref_name
)
1177 return git__prefixcmp(ref_name
, GIT_REFS_HEADS_DIR
) == 0;
1180 int git_reference_is_branch(const git_reference
*ref
)
1183 return git_reference__is_branch(ref
->name
);
1186 int git_reference__is_remote(const char *ref_name
)
1188 return git__prefixcmp(ref_name
, GIT_REFS_REMOTES_DIR
) == 0;
1191 int git_reference_is_remote(const git_reference
*ref
)
1194 return git_reference__is_remote(ref
->name
);
1197 int git_reference__is_tag(const char *ref_name
)
1199 return git__prefixcmp(ref_name
, GIT_REFS_TAGS_DIR
) == 0;
1202 int git_reference_is_tag(const git_reference
*ref
)
1205 return git_reference__is_tag(ref
->name
);
1208 int git_reference__is_note(const char *ref_name
)
1210 return git__prefixcmp(ref_name
, GIT_REFS_NOTES_DIR
) == 0;
1213 int git_reference_is_note(const git_reference
*ref
)
1216 return git_reference__is_note(ref
->name
);
1219 static int peel_error(int error
, git_reference
*ref
, const char* msg
)
1223 "The reference '%s' cannot be peeled - %s", git_reference_name(ref
), msg
);
1227 int git_reference_peel(
1228 git_object
**peeled
,
1230 git_otype target_type
)
1232 git_reference
*resolved
= NULL
;
1233 git_object
*target
= NULL
;
1238 if (ref
->type
== GIT_REF_OID
) {
1241 if ((error
= git_reference_resolve(&resolved
, ref
)) < 0)
1242 return peel_error(error
, ref
, "Cannot resolve reference");
1245 if (!git_oid_iszero(&resolved
->peel
)) {
1246 error
= git_object_lookup(&target
,
1247 git_reference_owner(ref
), &resolved
->peel
, GIT_OBJ_ANY
);
1249 error
= git_object_lookup(&target
,
1250 git_reference_owner(ref
), &resolved
->target
.oid
, GIT_OBJ_ANY
);
1254 peel_error(error
, ref
, "Cannot retrieve reference target");
1258 if (target_type
== GIT_OBJ_ANY
&& git_object_type(target
) != GIT_OBJ_TAG
)
1259 error
= git_object_dup(peeled
, target
);
1261 error
= git_object_peel(peeled
, target
, target_type
);
1264 git_object_free(target
);
1266 if (resolved
!= ref
)
1267 git_reference_free(resolved
);
1272 int git_reference__is_valid_name(const char *refname
, unsigned int flags
)
1274 if (git_reference__normalize_name(NULL
, refname
, flags
) < 0) {
1282 int git_reference_is_valid_name(const char *refname
)
1284 return git_reference__is_valid_name(refname
, GIT_REF_FORMAT_ALLOW_ONELEVEL
);
1287 const char *git_reference__shorthand(const char *name
)
1289 if (!git__prefixcmp(name
, GIT_REFS_HEADS_DIR
))
1290 return name
+ strlen(GIT_REFS_HEADS_DIR
);
1291 else if (!git__prefixcmp(name
, GIT_REFS_TAGS_DIR
))
1292 return name
+ strlen(GIT_REFS_TAGS_DIR
);
1293 else if (!git__prefixcmp(name
, GIT_REFS_REMOTES_DIR
))
1294 return name
+ strlen(GIT_REFS_REMOTES_DIR
);
1295 else if (!git__prefixcmp(name
, GIT_REFS_DIR
))
1296 return name
+ strlen(GIT_REFS_DIR
);
1298 /* No shorthands are avaiable, so just return the name */
1302 const char *git_reference_shorthand(const git_reference
*ref
)
1304 return git_reference__shorthand(ref
->name
);