]> git.proxmox.com Git - libgit2.git/blame - src/refspec.c
Merge pull request #735 from gregier/development
[libgit2.git] / src / refspec.c
CommitLineData
9c82357b 1/*
5e0de328 2 * Copyright (C) 2009-2012 the libgit2 contributors
9c82357b 3 *
bb742ede
VM
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.
9c82357b
CMN
6 */
7
92cb6aa9
CMN
8#include "git2/errors.h"
9
9c82357b
CMN
10#include "common.h"
11#include "refspec.h"
63f91e1c 12#include "util.h"
3fbcac89 13#include "posix.h"
9c82357b
CMN
14
15int git_refspec_parse(git_refspec *refspec, const char *str)
16{
17 char *delim;
18
19 memset(refspec, 0x0, sizeof(git_refspec));
20
21 if (*str == '+') {
22 refspec->force = 1;
23 str++;
24 }
25
26 delim = strchr(str, ':');
0ca7ca3e
CMN
27 if (delim == NULL) {
28 refspec->src = git__strdup(str);
3aa351ea
CMN
29 GITERR_CHECK_ALLOC(refspec->src);
30 return 0;
0ca7ca3e 31 }
9c82357b
CMN
32
33 refspec->src = git__strndup(str, delim - str);
3aa351ea 34 GITERR_CHECK_ALLOC(refspec->src);
9c82357b
CMN
35
36 refspec->dst = git__strdup(delim + 1);
37 if (refspec->dst == NULL) {
3286c408 38 git__free(refspec->src);
9c82357b 39 refspec->src = NULL;
3aa351ea 40 return -1;
9c82357b
CMN
41 }
42
3aa351ea 43 return 0;
9c82357b
CMN
44}
45
46const char *git_refspec_src(const git_refspec *refspec)
47{
4a3b18a6 48 return refspec == NULL ? NULL : refspec->src;
9c82357b
CMN
49}
50
51const char *git_refspec_dst(const git_refspec *refspec)
52{
4a3b18a6 53 return refspec == NULL ? NULL : refspec->dst;
9c82357b 54}
63f91e1c 55
3fbcac89 56int git_refspec_src_matches(const git_refspec *refspec, const char *refname)
63f91e1c 57{
3fbcac89
VM
58 if (refspec == NULL || refspec->src == NULL)
59 return false;
60
61 return (p_fnmatch(refspec->src, refname, 0) == 0);
63f91e1c 62}
92cb6aa9 63
87d9869f 64int git_refspec_transform(char *out, size_t outlen, const git_refspec *spec, const char *name)
92cb6aa9
CMN
65{
66 size_t baselen, namelen;
67
68 baselen = strlen(spec->dst);
3aa351ea
CMN
69 if (outlen <= baselen) {
70 giterr_set(GITERR_INVALID, "Reference name too long");
904b67e6 71 return GIT_EBUFS;
3aa351ea 72 }
92cb6aa9
CMN
73
74 /*
75 * No '*' at the end means that it's mapped to one specific local
76 * branch, so no actual transformation is needed.
77 */
78 if (spec->dst[baselen - 1] != '*') {
79 memcpy(out, spec->dst, baselen + 1); /* include '\0' */
3aa351ea 80 return 0;
92cb6aa9
CMN
81 }
82
83 /* There's a '*' at the end, so remove its length */
84 baselen--;
85
86 /* skip the prefix, -1 is for the '*' */
87 name += strlen(spec->src) - 1;
88
89 namelen = strlen(name);
90
3aa351ea
CMN
91 if (outlen <= baselen + namelen) {
92 giterr_set(GITERR_INVALID, "Reference name too long");
904b67e6 93 return GIT_EBUFS;
3aa351ea 94 }
92cb6aa9
CMN
95
96 memcpy(out, spec->dst, baselen);
97 memcpy(out + baselen, name, namelen + 1);
98
3aa351ea 99 return 0;
92cb6aa9 100}
97769280
RB
101
102int git_refspec_transform_r(git_buf *out, const git_refspec *spec, const char *name)
103{
3aa351ea
CMN
104 if (git_buf_sets(out, spec->dst) < 0)
105 return -1;
97769280
RB
106
107 /*
108 * No '*' at the end means that it's mapped to one specific local
109 * branch, so no actual transformation is needed.
110 */
fa6420f7 111 if (git_buf_len(out) > 0 && out->ptr[git_buf_len(out) - 1] != '*')
3aa351ea 112 return 0;
97769280 113
fa6420f7 114 git_buf_truncate(out, git_buf_len(out) - 1); /* remove trailing '*' */
279afd2a 115 git_buf_puts(out, name + strlen(spec->src) - 1);
97769280 116
cb8a7961 117 if (git_buf_oom(out))
3aa351ea 118 return -1;
cb8a7961
VM
119
120 return 0;
97769280 121}
cb8a7961 122