]>
Commit | Line | Data |
---|---|---|
9c82357b | 1 | /* |
bb742ede | 2 | * Copyright (C) 2009-2011 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" |
9c82357b CMN |
13 | |
14 | int git_refspec_parse(git_refspec *refspec, const char *str) | |
15 | { | |
16 | char *delim; | |
17 | ||
18 | memset(refspec, 0x0, sizeof(git_refspec)); | |
19 | ||
20 | if (*str == '+') { | |
21 | refspec->force = 1; | |
22 | str++; | |
23 | } | |
24 | ||
25 | delim = strchr(str, ':'); | |
26 | if (delim == NULL) | |
27 | return git__throw(GIT_EOBJCORRUPTED, "Failed to parse refspec. No ':'"); | |
28 | ||
29 | refspec->src = git__strndup(str, delim - str); | |
30 | if (refspec->src == NULL) | |
31 | return GIT_ENOMEM; | |
32 | ||
33 | refspec->dst = git__strdup(delim + 1); | |
34 | if (refspec->dst == NULL) { | |
35 | free(refspec->src); | |
36 | refspec->src = NULL; | |
37 | return GIT_ENOMEM; | |
38 | } | |
39 | ||
40 | return GIT_SUCCESS; | |
41 | } | |
42 | ||
43 | const char *git_refspec_src(const git_refspec *refspec) | |
44 | { | |
45 | return refspec->src; | |
46 | } | |
47 | ||
48 | const char *git_refspec_dst(const git_refspec *refspec) | |
49 | { | |
50 | return refspec->dst; | |
51 | } | |
63f91e1c CMN |
52 | |
53 | int git_refspec_src_match(const git_refspec *refspec, const char *refname) | |
54 | { | |
55 | return git__fnmatch(refspec->src, refname, 0); | |
56 | } | |
92cb6aa9 | 57 | |
87d9869f | 58 | int git_refspec_transform(char *out, size_t outlen, const git_refspec *spec, const char *name) |
92cb6aa9 CMN |
59 | { |
60 | size_t baselen, namelen; | |
61 | ||
62 | baselen = strlen(spec->dst); | |
63 | if (outlen <= baselen) | |
64 | return git__throw(GIT_EINVALIDREFNAME, "Reference name too long"); | |
65 | ||
66 | /* | |
67 | * No '*' at the end means that it's mapped to one specific local | |
68 | * branch, so no actual transformation is needed. | |
69 | */ | |
70 | if (spec->dst[baselen - 1] != '*') { | |
71 | memcpy(out, spec->dst, baselen + 1); /* include '\0' */ | |
72 | return GIT_SUCCESS; | |
73 | } | |
74 | ||
75 | /* There's a '*' at the end, so remove its length */ | |
76 | baselen--; | |
77 | ||
78 | /* skip the prefix, -1 is for the '*' */ | |
79 | name += strlen(spec->src) - 1; | |
80 | ||
81 | namelen = strlen(name); | |
82 | ||
83 | if (outlen <= baselen + namelen) | |
84 | return git__throw(GIT_EINVALIDREFNAME, "Reference name too long"); | |
85 | ||
86 | memcpy(out, spec->dst, baselen); | |
87 | memcpy(out + baselen, name, namelen + 1); | |
88 | ||
89 | return GIT_SUCCESS; | |
90 | } |