]>
git.proxmox.com Git - libgit2.git/blob - src/transport_local.c
2 * Copyright (C) 2009-2011 the libgit2 contributors
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.
8 #include "git2/types.h"
9 #include "git2/transport.h"
11 #include "git2/repository.h"
12 #include "git2/object.h"
15 #include "transport.h"
22 git_headarray wants_list
;
26 * Try to open the url as a git directory. The direction doesn't
27 * matter in this case because we're calulating the heads ourselves.
29 static int local_connect(git_transport
*transport
, int GIT_UNUSED(direction
))
33 transport_local
*t
= (transport_local
*) transport
;
35 const char file_prefix
[] = "file://";
36 GIT_UNUSED_ARG(direction
);
38 /* The repo layer doesn't want the prefix */
39 if (!git__prefixcmp(transport
->url
, file_prefix
))
40 path
= transport
->url
+ strlen(file_prefix
);
42 path
= transport
->url
;
44 error
= git_repository_open(&repo
, path
);
45 if (error
< GIT_SUCCESS
)
46 return git__rethrow(error
, "Failed to open remote");
49 t
->parent
.connected
= 1;
54 static int add_ref(const char *name
, git_repository
*repo
, git_vector
*vec
)
56 const char peeled
[] = "^{}";
57 git_remote_head
*head
;
59 git_object
*obj
= NULL
;
60 int error
= GIT_SUCCESS
, peel_len
, ret
;
62 head
= git__malloc(sizeof(git_remote_head
));
66 head
->name
= git__strdup(name
);
67 if (head
->name
== NULL
) {
72 error
= git_reference_lookup(&ref
, repo
, name
);
73 if (error
< GIT_SUCCESS
)
76 error
= git_reference_resolve(&ref
, ref
);
77 if (error
< GIT_SUCCESS
)
80 git_oid_cpy(&head
->oid
, git_reference_oid(ref
));
82 error
= git_vector_insert(vec
, head
);
83 if (error
< GIT_SUCCESS
)
86 /* If it's not a tag, we don't need to try to peel it */
87 if (git__prefixcmp(name
, GIT_REFS_TAGS_DIR
))
90 error
= git_object_lookup(&obj
, repo
, &head
->oid
, GIT_OBJ_ANY
);
91 if (error
< GIT_SUCCESS
) {
92 git__rethrow(error
, "Failed to lookup object");
95 /* If it's not an annotated tag, just get out */
96 if (git_object_type(obj
) != GIT_OBJ_TAG
)
99 /* And if it's a tag, peel it, and add it to the list */
100 head
= git__malloc(sizeof(git_remote_head
));
101 peel_len
= strlen(name
) + strlen(peeled
);
102 head
->name
= git__malloc(peel_len
+ 1);
103 ret
= p_snprintf(head
->name
, peel_len
+ 1, "%s%s", name
, peeled
);
104 if (ret
>= peel_len
+ 1) {
105 error
= git__throw(GIT_ERROR
, "The string is magically to long");
108 git_oid_cpy(&head
->oid
, git_tag_target_oid((git_tag
*) obj
));
110 error
= git_vector_insert(vec
, head
);
111 if (error
< GIT_SUCCESS
)
115 git_object_close(obj
);
116 if (error
< GIT_SUCCESS
) {
123 static int local_ls(git_transport
*transport
, git_headarray
*array
)
127 git_repository
*repo
;
130 transport_local
*t
= (transport_local
*) transport
;
132 assert(transport
&& transport
->connected
);
136 error
= git_reference_listall(&refs
, repo
, GIT_REF_LISTALL
);
137 if (error
< GIT_SUCCESS
)
138 return git__rethrow(error
, "Failed to list remote heads");
140 vec
= git__malloc(sizeof(git_vector
));
146 error
= git_vector_init(vec
, refs
.count
, NULL
);
147 if (error
< GIT_SUCCESS
)
150 /* Sort the references first */
151 git__tsort((void **)refs
.strings
, refs
.count
, &git__strcmp_cb
);
154 error
= add_ref(GIT_HEAD_FILE
, repo
, vec
);
155 if (error
< GIT_SUCCESS
)
158 for (i
= 0; i
< refs
.count
; ++i
) {
159 error
= add_ref(refs
.strings
[i
], repo
, vec
);
160 if (error
< GIT_SUCCESS
)
164 array
->len
= vec
->length
;
165 array
->heads
= (git_remote_head
**)vec
->contents
;
171 git_strarray_free(&refs
);
176 static int local_send_wants(git_transport
*transport
, git_headarray
*array
)
178 transport_local
*t
= (transport_local
*) transport
;
179 git_headarray
*wants
= &t
->wants_list
;
182 * We need to store the list of wanted references so we can figure
183 * out what to transmit later.
185 wants
->len
= array
->len
;
186 wants
->heads
= array
->heads
;
188 /* We're local anyway, so we don't need this */
192 static int local_close(git_transport
*GIT_UNUSED(transport
))
195 GIT_UNUSED_ARG(transport
);
199 static void local_free(git_transport
*transport
)
202 transport_local
*t
= (transport_local
*) transport
;
203 git_vector
*vec
= t
->refs
;
207 for (i
= 0; i
< vec
->length
; ++i
) {
208 git_remote_head
*h
= git_vector_get(vec
, i
);
212 git_vector_free(vec
);
214 git_repository_free(t
->repo
);
223 int git_transport_local(git_transport
**out
)
227 t
= git__malloc(sizeof(transport_local
));
231 t
->parent
.connect
= local_connect
;
232 t
->parent
.ls
= local_ls
;
233 t
->parent
.send_wants
= local_send_wants
;
234 t
->parent
.close
= local_close
;
235 t
->parent
.free
= local_free
;
237 *out
= (git_transport
*) t
;