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.
Files changed (158) hide show
  1. data/README.md +3 -3
  2. data/Rakefile +3 -1
  3. data/ext/rugged/rugged.c +30 -0
  4. data/ext/rugged/rugged.h +9 -0
  5. data/ext/rugged/rugged_branch.c +306 -0
  6. data/ext/rugged/rugged_config.c +16 -13
  7. data/ext/rugged/rugged_index.c +25 -0
  8. data/ext/rugged/rugged_object.c +6 -2
  9. data/ext/rugged/rugged_reference.c +11 -18
  10. data/ext/rugged/rugged_revwalk.c +1 -1
  11. data/lib/rugged.rb +1 -0
  12. data/lib/rugged/branch.rb +28 -0
  13. data/lib/rugged/commit.rb +5 -5
  14. data/lib/rugged/repository.rb +32 -7
  15. data/lib/rugged/tag.rb +5 -1
  16. data/lib/rugged/version.rb +1 -1
  17. data/test/branch_test.rb +227 -0
  18. data/test/config_test.rb +1 -1
  19. data/test/fixtures/testrepo.git/objects/4b/825dc642cb6eb9a060e54bf8d69288fbee4904 +0 -0
  20. data/test/fixtures/testrepo.git/objects/a3/e05719b428a2d0ed7a55c4ce53dcc5768c6d5e +0 -0
  21. data/test/index_test.rb +31 -0
  22. data/test/index_test.rb~ +218 -0
  23. data/test/lib_test.rb +22 -0
  24. data/test/reference_test.rb +5 -3
  25. data/vendor/libgit2/Makefile.embed +1 -1
  26. data/vendor/libgit2/include/git2.h +1 -0
  27. data/vendor/libgit2/include/git2/branch.h +17 -13
  28. data/vendor/libgit2/include/git2/checkout.h +83 -22
  29. data/vendor/libgit2/include/git2/clone.h +6 -3
  30. data/vendor/libgit2/include/git2/common.h +1 -8
  31. data/vendor/libgit2/include/git2/config.h +185 -26
  32. data/vendor/libgit2/include/git2/diff.h +229 -17
  33. data/vendor/libgit2/include/git2/errors.h +39 -1
  34. data/vendor/libgit2/include/git2/ignore.h +6 -3
  35. data/vendor/libgit2/include/git2/indexer.h +1 -0
  36. data/vendor/libgit2/include/git2/merge.h +1 -1
  37. data/vendor/libgit2/include/git2/object.h +7 -4
  38. data/vendor/libgit2/include/git2/odb.h +4 -2
  39. data/vendor/libgit2/include/git2/odb_backend.h +6 -0
  40. data/vendor/libgit2/include/git2/oid.h +2 -0
  41. data/vendor/libgit2/include/git2/pack.h +89 -0
  42. data/vendor/libgit2/include/git2/refs.h +88 -0
  43. data/vendor/libgit2/include/git2/refspec.h +0 -8
  44. data/vendor/libgit2/include/git2/remote.h +34 -1
  45. data/vendor/libgit2/include/git2/repository.h +238 -6
  46. data/vendor/libgit2/include/git2/reset.h +4 -1
  47. data/vendor/libgit2/include/git2/revwalk.h +1 -1
  48. data/vendor/libgit2/include/git2/status.h +19 -14
  49. data/vendor/libgit2/include/git2/strarray.h +54 -0
  50. data/vendor/libgit2/include/git2/submodule.h +451 -45
  51. data/vendor/libgit2/include/git2/tag.h +16 -0
  52. data/vendor/libgit2/include/git2/tree.h +2 -2
  53. data/vendor/libgit2/include/git2/types.h +4 -0
  54. data/vendor/libgit2/src/amiga/map.c +4 -7
  55. data/vendor/libgit2/src/attr.c +21 -13
  56. data/vendor/libgit2/src/attr.h +3 -1
  57. data/vendor/libgit2/src/attr_file.c +14 -14
  58. data/vendor/libgit2/src/attr_file.h +6 -5
  59. data/vendor/libgit2/src/blob.c +22 -12
  60. data/vendor/libgit2/src/branch.c +62 -66
  61. data/vendor/libgit2/src/buffer.c +63 -14
  62. data/vendor/libgit2/src/buffer.h +4 -0
  63. data/vendor/libgit2/src/cache.c +5 -4
  64. data/vendor/libgit2/src/checkout.c +381 -159
  65. data/vendor/libgit2/src/clone.c +221 -94
  66. data/vendor/libgit2/src/common.h +13 -3
  67. data/vendor/libgit2/src/compress.c +53 -0
  68. data/vendor/libgit2/src/compress.h +16 -0
  69. data/vendor/libgit2/src/config.c +380 -175
  70. data/vendor/libgit2/src/config.h +2 -5
  71. data/vendor/libgit2/src/config_file.c +63 -46
  72. data/vendor/libgit2/src/config_file.h +16 -4
  73. data/vendor/libgit2/src/crlf.c +4 -3
  74. data/vendor/libgit2/src/delta.c +491 -0
  75. data/vendor/libgit2/src/delta.h +112 -0
  76. data/vendor/libgit2/src/diff.c +310 -67
  77. data/vendor/libgit2/src/diff.h +10 -1
  78. data/vendor/libgit2/src/diff_output.c +1030 -337
  79. data/vendor/libgit2/src/diff_output.h +86 -0
  80. data/vendor/libgit2/src/errors.c +10 -1
  81. data/vendor/libgit2/src/fetch.c +108 -24
  82. data/vendor/libgit2/src/filebuf.c +8 -2
  83. data/vendor/libgit2/src/fileops.c +342 -177
  84. data/vendor/libgit2/src/fileops.h +84 -7
  85. data/vendor/libgit2/src/filter.c +0 -35
  86. data/vendor/libgit2/src/filter.h +0 -12
  87. data/vendor/libgit2/src/{compat/fnmatch.c → fnmatch.c} +16 -4
  88. data/vendor/libgit2/src/{compat/fnmatch.h → fnmatch.h} +4 -3
  89. data/vendor/libgit2/src/global.c +4 -0
  90. data/vendor/libgit2/src/ignore.c +122 -23
  91. data/vendor/libgit2/src/ignore.h +1 -0
  92. data/vendor/libgit2/src/index.c +56 -10
  93. data/vendor/libgit2/src/index.h +2 -0
  94. data/vendor/libgit2/src/indexer.c +8 -9
  95. data/vendor/libgit2/src/iterator.c +244 -31
  96. data/vendor/libgit2/src/iterator.h +30 -1
  97. data/vendor/libgit2/src/message.c +1 -1
  98. data/vendor/libgit2/src/netops.c +44 -4
  99. data/vendor/libgit2/src/object.c +80 -69
  100. data/vendor/libgit2/src/object.h +39 -0
  101. data/vendor/libgit2/src/odb.c +79 -15
  102. data/vendor/libgit2/src/odb.h +20 -5
  103. data/vendor/libgit2/src/odb_pack.c +65 -33
  104. data/vendor/libgit2/src/oid.c +0 -3
  105. data/vendor/libgit2/src/pack-objects.c +1315 -0
  106. data/vendor/libgit2/src/pack-objects.h +87 -0
  107. data/vendor/libgit2/src/pack.c +36 -12
  108. data/vendor/libgit2/src/pack.h +1 -0
  109. data/vendor/libgit2/src/path.c +42 -9
  110. data/vendor/libgit2/src/path.h +14 -0
  111. data/vendor/libgit2/src/pkt.c +52 -2
  112. data/vendor/libgit2/src/pkt.h +10 -0
  113. data/vendor/libgit2/src/pool.h +11 -0
  114. data/vendor/libgit2/src/posix.h +8 -0
  115. data/vendor/libgit2/src/protocol.c +24 -2
  116. data/vendor/libgit2/src/protocol.h +4 -0
  117. data/vendor/libgit2/src/reflog.c +1 -1
  118. data/vendor/libgit2/src/refs.c +292 -124
  119. data/vendor/libgit2/src/refs.h +4 -2
  120. data/vendor/libgit2/src/refspec.c +117 -19
  121. data/vendor/libgit2/src/refspec.h +19 -0
  122. data/vendor/libgit2/src/remote.c +152 -48
  123. data/vendor/libgit2/src/remote.h +4 -1
  124. data/vendor/libgit2/src/repo_template.h +58 -0
  125. data/vendor/libgit2/src/repository.c +594 -179
  126. data/vendor/libgit2/src/repository.h +23 -22
  127. data/vendor/libgit2/src/reset.c +71 -29
  128. data/vendor/libgit2/src/revparse.c +26 -17
  129. data/vendor/libgit2/src/revwalk.c +36 -19
  130. data/vendor/libgit2/src/sha1.h +7 -0
  131. data/vendor/libgit2/src/{sha1.c → sha1/sha1.c} +0 -0
  132. data/vendor/libgit2/src/signature.c +12 -10
  133. data/vendor/libgit2/src/status.c +52 -6
  134. data/vendor/libgit2/src/submodule.c +1363 -255
  135. data/vendor/libgit2/src/submodule.h +102 -0
  136. data/vendor/libgit2/src/tag.c +42 -26
  137. data/vendor/libgit2/src/thread-utils.h +7 -7
  138. data/vendor/libgit2/src/transport.h +15 -1
  139. data/vendor/libgit2/src/transports/git.c +1 -1
  140. data/vendor/libgit2/src/transports/http.c +197 -36
  141. data/vendor/libgit2/src/tree.c +3 -3
  142. data/vendor/libgit2/src/unix/map.c +2 -0
  143. data/vendor/libgit2/src/unix/posix.h +1 -8
  144. data/vendor/libgit2/src/util.c +6 -1
  145. data/vendor/libgit2/src/util.h +7 -0
  146. data/vendor/libgit2/src/vector.c +16 -0
  147. data/vendor/libgit2/src/vector.h +1 -0
  148. data/vendor/libgit2/src/win32/dir.c +8 -21
  149. data/vendor/libgit2/src/win32/findfile.c +149 -0
  150. data/vendor/libgit2/src/win32/findfile.h +23 -0
  151. data/vendor/libgit2/src/win32/posix.h +3 -7
  152. data/vendor/libgit2/src/win32/posix_w32.c +44 -102
  153. data/vendor/libgit2/src/win32/pthread.c +68 -0
  154. data/vendor/libgit2/src/win32/pthread.h +7 -0
  155. data/vendor/libgit2/src/win32/utf-conv.c +60 -71
  156. data/vendor/libgit2/src/win32/utf-conv.h +4 -3
  157. metadata +70 -71
  158. data/vendor/libgit2/include/git2/windows.h +0 -59
@@ -0,0 +1,16 @@
1
+ /*
2
+ * Copyright (C) 2009-2012 the libgit2 contributors
3
+ *
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.
6
+ */
7
+ #ifndef INCLUDE_compress_h__
8
+ #define INCLUDE_compress_h__
9
+
10
+ #include "common.h"
11
+
12
+ #include "buffer.h"
13
+
14
+ int git__compress(git_buf *buf, const void *buff, size_t len);
15
+
16
+ #endif /* INCLUDE_compress_h__ */
@@ -17,21 +17,29 @@
17
17
  #include <ctype.h>
18
18
 
19
19
  typedef struct {
20
+ git_refcount rc;
21
+
20
22
  git_config_file *file;
21
- int priority;
23
+ unsigned int level;
22
24
  } file_internal;
23
25
 
26
+ static void file_internal_free(file_internal *internal)
27
+ {
28
+ git_config_file *file;
29
+
30
+ file = internal->file;
31
+ file->free(file);
32
+ git__free(internal);
33
+ }
34
+
24
35
  static void config_free(git_config *cfg)
25
36
  {
26
37
  unsigned int i;
27
- git_config_file *file;
28
38
  file_internal *internal;
29
39
 
30
40
  for(i = 0; i < cfg->files.length; ++i){
31
41
  internal = git_vector_get(&cfg->files, i);
32
- file = internal->file;
33
- file->free(file);
34
- git__free(internal);
42
+ GIT_REFCOUNT_DEC(internal, file_internal_free);
35
43
  }
36
44
 
37
45
  git_vector_free(&cfg->files);
@@ -51,7 +59,7 @@ static int config_backend_cmp(const void *a, const void *b)
51
59
  const file_internal *bk_a = (const file_internal *)(a);
52
60
  const file_internal *bk_b = (const file_internal *)(b);
53
61
 
54
- return bk_b->priority - bk_a->priority;
62
+ return bk_b->level - bk_a->level;
55
63
  }
56
64
 
57
65
  int git_config_new(git_config **out)
@@ -73,20 +81,25 @@ int git_config_new(git_config **out)
73
81
  return 0;
74
82
  }
75
83
 
76
- int git_config_add_file_ondisk(git_config *cfg, const char *path, int priority)
84
+ int git_config_add_file_ondisk(
85
+ git_config *cfg,
86
+ const char *path,
87
+ unsigned int level,
88
+ int force)
77
89
  {
78
90
  git_config_file *file = NULL;
91
+ int res;
79
92
 
80
93
  if (git_config_file__ondisk(&file, path) < 0)
81
94
  return -1;
82
95
 
83
- if (git_config_add_file(cfg, file, priority) < 0) {
96
+ if ((res = git_config_add_file(cfg, file, level, force)) < 0) {
84
97
  /*
85
98
  * free manually; the file is not owned by the config
86
99
  * instance yet and will not be freed on cleanup
87
100
  */
88
101
  file->free(file);
89
- return -1;
102
+ return res;
90
103
  }
91
104
 
92
105
  return 0;
@@ -97,7 +110,7 @@ int git_config_open_ondisk(git_config **cfg, const char *path)
97
110
  if (git_config_new(cfg) < 0)
98
111
  return -1;
99
112
 
100
- if (git_config_add_file_ondisk(*cfg, path, 1) < 0) {
113
+ if (git_config_add_file_ondisk(*cfg, path, GIT_CONFIG_LEVEL_LOCAL, 0) < 0) {
101
114
  git_config_free(*cfg);
102
115
  return -1;
103
116
  }
@@ -105,30 +118,152 @@ int git_config_open_ondisk(git_config **cfg, const char *path)
105
118
  return 0;
106
119
  }
107
120
 
108
- int git_config_add_file(git_config *cfg, git_config_file *file, int priority)
121
+ static int find_internal_file_by_level(
122
+ file_internal **internal_out,
123
+ git_config *cfg,
124
+ int level)
125
+ {
126
+ int pos = -1;
127
+ file_internal *internal;
128
+ unsigned int i;
129
+
130
+ assert(cfg->files.length);
131
+
132
+ /* when passing GIT_CONFIG_HIGHEST_LEVEL, the idea is to get the config file
133
+ * which has the highest level. As config files are stored in a vector
134
+ * sorted by decreasing order of level, getting the file at position 0
135
+ * will do the job.
136
+ */
137
+ if (level == GIT_CONFIG_HIGHEST_LEVEL) {
138
+ pos = 0;
139
+ } else {
140
+ git_vector_foreach(&cfg->files, i, internal) {
141
+ if (internal->level == (unsigned int)level)
142
+ pos = i;
143
+ }
144
+ }
145
+
146
+ if (pos == -1) {
147
+ giterr_set(GITERR_CONFIG,
148
+ "No config file exists for the given level '%i'", level);
149
+ return GIT_ENOTFOUND;
150
+ }
151
+
152
+ *internal_out = git_vector_get(&cfg->files, pos);
153
+
154
+ return 0;
155
+ }
156
+
157
+ static int duplicate_level(void **old_raw, void *new_raw)
158
+ {
159
+ file_internal **old = (file_internal **)old_raw;
160
+
161
+ GIT_UNUSED(new_raw);
162
+
163
+ giterr_set(GITERR_CONFIG, "A file with the same level (%i) has already been added to the config", (*old)->level);
164
+ return GIT_EEXISTS;
165
+ }
166
+
167
+ static void try_remove_existing_file_internal(
168
+ git_config *cfg,
169
+ unsigned int level)
170
+ {
171
+ int pos = -1;
172
+ file_internal *internal;
173
+ unsigned int i;
174
+
175
+ git_vector_foreach(&cfg->files, i, internal) {
176
+ if (internal->level == level)
177
+ pos = i;
178
+ }
179
+
180
+ if (pos == -1)
181
+ return;
182
+
183
+ internal = git_vector_get(&cfg->files, pos);
184
+
185
+ if (git_vector_remove(&cfg->files, pos) < 0)
186
+ return;
187
+
188
+ GIT_REFCOUNT_DEC(internal, file_internal_free);
189
+ }
190
+
191
+ static int git_config__add_internal(
192
+ git_config *cfg,
193
+ file_internal *internal,
194
+ unsigned int level,
195
+ int force)
196
+ {
197
+ int result;
198
+
199
+ /* delete existing config file for level if it exists */
200
+ if (force)
201
+ try_remove_existing_file_internal(cfg, level);
202
+
203
+ if ((result = git_vector_insert_sorted(&cfg->files,
204
+ internal, &duplicate_level)) < 0)
205
+ return result;
206
+
207
+ git_vector_sort(&cfg->files);
208
+ internal->file->cfg = cfg;
209
+
210
+ GIT_REFCOUNT_INC(internal);
211
+
212
+ return 0;
213
+ }
214
+
215
+ int git_config_open_level(
216
+ git_config **cfg_out,
217
+ git_config *cfg_parent,
218
+ unsigned int level)
219
+ {
220
+ git_config *cfg;
221
+ file_internal *internal;
222
+ int res;
223
+
224
+ if ((res = find_internal_file_by_level(&internal, cfg_parent, level)) < 0)
225
+ return res;
226
+
227
+ if ((res = git_config_new(&cfg)) < 0)
228
+ return res;
229
+
230
+ if ((res = git_config__add_internal(cfg, internal, level, true)) < 0) {
231
+ git_config_free(cfg);
232
+ return res;
233
+ }
234
+
235
+ *cfg_out = cfg;
236
+
237
+ return 0;
238
+ }
239
+
240
+ int git_config_add_file(
241
+ git_config *cfg,
242
+ git_config_file *file,
243
+ unsigned int level,
244
+ int force)
109
245
  {
110
246
  file_internal *internal;
111
247
  int result;
112
248
 
113
249
  assert(cfg && file);
114
250
 
115
- if ((result = file->open(file)) < 0)
251
+ if ((result = file->open(file, level)) < 0)
116
252
  return result;
117
253
 
118
254
  internal = git__malloc(sizeof(file_internal));
119
255
  GITERR_CHECK_ALLOC(internal);
120
256
 
257
+ memset(internal, 0x0, sizeof(file_internal));
258
+
121
259
  internal->file = file;
122
- internal->priority = priority;
260
+ internal->level = level;
123
261
 
124
- if (git_vector_insert(&cfg->files, internal) < 0) {
262
+ if ((result = git_config__add_internal(cfg, internal, level, force)) < 0) {
125
263
  git__free(internal);
126
- return -1;
264
+ return result;
127
265
  }
128
266
 
129
- git_vector_sort(&cfg->files);
130
- internal->file->cfg = cfg;
131
-
132
267
  return 0;
133
268
  }
134
269
 
@@ -137,7 +272,7 @@ int git_config_add_file(git_config *cfg, git_config_file *file, int priority)
137
272
  */
138
273
 
139
274
  int git_config_foreach(
140
- git_config *cfg, int (*fn)(const char *, const char *, void *), void *data)
275
+ git_config *cfg, int (*fn)(const git_config_entry *, void *), void *data)
141
276
  {
142
277
  return git_config_foreach_match(cfg, NULL, fn, data);
143
278
  }
@@ -145,7 +280,7 @@ int git_config_foreach(
145
280
  int git_config_foreach_match(
146
281
  git_config *cfg,
147
282
  const char *regexp,
148
- int (*fn)(const char *, const char *, void *),
283
+ int (*fn)(const git_config_entry *, void *),
149
284
  void *data)
150
285
  {
151
286
  int ret = 0;
@@ -164,10 +299,8 @@ int git_config_foreach_match(
164
299
 
165
300
  int git_config_delete(git_config *cfg, const char *name)
166
301
  {
167
- file_internal *internal;
168
302
  git_config_file *file;
169
-
170
- assert(cfg->files.length);
303
+ file_internal *internal;
171
304
 
172
305
  internal = git_vector_get(&cfg->files, 0);
173
306
  file = internal->file;
@@ -198,10 +331,8 @@ int git_config_set_bool(git_config *cfg, const char *name, int value)
198
331
 
199
332
  int git_config_set_string(git_config *cfg, const char *name, const char *value)
200
333
  {
201
- file_internal *internal;
202
334
  git_config_file *file;
203
-
204
- assert(cfg->files.length);
335
+ file_internal *internal;
205
336
 
206
337
  internal = git_vector_get(&cfg->files, 0);
207
338
  file = internal->file;
@@ -209,105 +340,9 @@ int git_config_set_string(git_config *cfg, const char *name, const char *value)
209
340
  return file->set(file, name, value);
210
341
  }
211
342
 
212
- static int parse_int64(int64_t *out, const char *value)
213
- {
214
- const char *num_end;
215
- int64_t num;
216
-
217
- if (git__strtol64(&num, value, &num_end, 0) < 0)
218
- return -1;
219
-
220
- switch (*num_end) {
221
- case 'g':
222
- case 'G':
223
- num *= 1024;
224
- /* fallthrough */
225
-
226
- case 'm':
227
- case 'M':
228
- num *= 1024;
229
- /* fallthrough */
230
-
231
- case 'k':
232
- case 'K':
233
- num *= 1024;
234
-
235
- /* check that that there are no more characters after the
236
- * given modifier suffix */
237
- if (num_end[1] != '\0')
238
- return -1;
239
-
240
- /* fallthrough */
241
-
242
- case '\0':
243
- *out = num;
244
- return 0;
245
-
246
- default:
247
- return -1;
248
- }
249
- }
250
-
251
- static int parse_int32(int32_t *out, const char *value)
252
- {
253
- int64_t tmp;
254
- int32_t truncate;
255
-
256
- if (parse_int64(&tmp, value) < 0)
257
- return -1;
258
-
259
- truncate = tmp & 0xFFFFFFFF;
260
- if (truncate != tmp)
261
- return -1;
262
-
263
- *out = truncate;
264
- return 0;
265
- }
266
-
267
343
  /***********
268
344
  * Getters
269
345
  ***********/
270
- int git_config_lookup_map_value(
271
- git_cvar_map *maps, size_t map_n, const char *value, int *out)
272
- {
273
- size_t i;
274
-
275
- if (!value)
276
- return GIT_ENOTFOUND;
277
-
278
- for (i = 0; i < map_n; ++i) {
279
- git_cvar_map *m = maps + i;
280
-
281
- switch (m->cvar_type) {
282
- case GIT_CVAR_FALSE:
283
- case GIT_CVAR_TRUE: {
284
- int bool_val;
285
-
286
- if (git__parse_bool(&bool_val, value) == 0 &&
287
- bool_val == (int)m->cvar_type) {
288
- *out = m->map_value;
289
- return 0;
290
- }
291
- break;
292
- }
293
-
294
- case GIT_CVAR_INT32:
295
- if (parse_int32(out, value) == 0)
296
- return 0;
297
- break;
298
-
299
- case GIT_CVAR_STRING:
300
- if (strcasecmp(value, m->str_match) == 0) {
301
- *out = m->map_value;
302
- return 0;
303
- }
304
- break;
305
- }
306
- }
307
-
308
- return GIT_ENOTFOUND;
309
- }
310
-
311
346
  int git_config_get_mapped(
312
347
  int *out,
313
348
  git_config *cfg,
@@ -318,16 +353,10 @@ int git_config_get_mapped(
318
353
  const char *value;
319
354
  int ret;
320
355
 
321
- ret = git_config_get_string(&value, cfg, name);
322
- if (ret < 0)
356
+ if ((ret = git_config_get_string(&value, cfg, name)) < 0)
323
357
  return ret;
324
358
 
325
- if (!git_config_lookup_map_value(maps, map_n, value, out))
326
- return 0;
327
-
328
- giterr_set(GITERR_CONFIG,
329
- "Failed to map the '%s' config variable with a valid value", name);
330
- return -1;
359
+ return git_config_lookup_map_value(out, maps, map_n, value);
331
360
  }
332
361
 
333
362
  int git_config_get_int64(int64_t *out, git_config *cfg, const char *name)
@@ -335,16 +364,10 @@ int git_config_get_int64(int64_t *out, git_config *cfg, const char *name)
335
364
  const char *value;
336
365
  int ret;
337
366
 
338
- ret = git_config_get_string(&value, cfg, name);
339
- if (ret < 0)
367
+ if ((ret = git_config_get_string(&value, cfg, name)) < 0)
340
368
  return ret;
341
369
 
342
- if (parse_int64(out, value) < 0) {
343
- giterr_set(GITERR_CONFIG, "Failed to parse '%s' as an integer", value);
344
- return -1;
345
- }
346
-
347
- return 0;
370
+ return git_config_parse_int64(out, value);
348
371
  }
349
372
 
350
373
  int git_config_get_int32(int32_t *out, git_config *cfg, const char *name)
@@ -352,16 +375,10 @@ int git_config_get_int32(int32_t *out, git_config *cfg, const char *name)
352
375
  const char *value;
353
376
  int ret;
354
377
 
355
- ret = git_config_get_string(&value, cfg, name);
356
- if (ret < 0)
378
+ if ((ret = git_config_get_string(&value, cfg, name)) < 0)
357
379
  return ret;
358
380
 
359
- if (parse_int32(out, value) < 0) {
360
- giterr_set(GITERR_CONFIG, "Failed to parse '%s' as a 32-bit integer", value);
361
- return -1;
362
- }
363
-
364
- return 0;
381
+ return git_config_parse_int32(out, value);
365
382
  }
366
383
 
367
384
  int git_config_get_bool(int *out, git_config *cfg, const char *name)
@@ -369,20 +386,24 @@ int git_config_get_bool(int *out, git_config *cfg, const char *name)
369
386
  const char *value;
370
387
  int ret;
371
388
 
372
- ret = git_config_get_string(&value, cfg, name);
373
- if (ret < 0)
389
+ if ((ret = git_config_get_string(&value, cfg, name)) < 0)
374
390
  return ret;
375
391
 
376
- if (git__parse_bool(out, value) == 0)
377
- return 0;
392
+ return git_config_parse_bool(out, value);
393
+ }
378
394
 
379
- if (parse_int32(out, value) == 0) {
380
- *out = !!(*out);
381
- return 0;
382
- }
395
+ static int get_string_at_file(const char **out, git_config_file *file, const char *name)
396
+ {
397
+ const git_config_entry *entry;
398
+ int res;
383
399
 
384
- giterr_set(GITERR_CONFIG, "Failed to parse '%s' as a boolean value", value);
385
- return -1;
400
+ *out = NULL;
401
+
402
+ res = file->get(file, name, &entry);
403
+ if (res != GIT_ENOTFOUND)
404
+ *out = entry->value;
405
+
406
+ return res;
386
407
  }
387
408
 
388
409
  int git_config_get_string(const char **out, git_config *cfg, const char *name)
@@ -392,6 +413,23 @@ int git_config_get_string(const char **out, git_config *cfg, const char *name)
392
413
 
393
414
  assert(cfg->files.length);
394
415
 
416
+ git_vector_foreach(&cfg->files, i, internal) {
417
+ int res = get_string_at_file(out, internal->file, name);
418
+
419
+ if (res != GIT_ENOTFOUND)
420
+ return res;
421
+ }
422
+
423
+ return GIT_ENOTFOUND;
424
+ }
425
+
426
+ int git_config_get_config_entry(const git_config_entry **out, git_config *cfg, const char *name)
427
+ {
428
+ file_internal *internal;
429
+ unsigned int i;
430
+
431
+ assert(cfg->files.length);
432
+
395
433
  *out = NULL;
396
434
 
397
435
  git_vector_foreach(&cfg->files, i, internal) {
@@ -405,7 +443,7 @@ int git_config_get_string(const char **out, git_config *cfg, const char *name)
405
443
  }
406
444
 
407
445
  int git_config_get_multivar(git_config *cfg, const char *name, const char *regexp,
408
- int (*fn)(const char *value, void *data), void *data)
446
+ int (*fn)(const git_config_entry *entry, void *data), void *data)
409
447
  {
410
448
  file_internal *internal;
411
449
  git_config_file *file;
@@ -431,25 +469,27 @@ int git_config_get_multivar(git_config *cfg, const char *name, const char *regex
431
469
 
432
470
  int git_config_set_multivar(git_config *cfg, const char *name, const char *regexp, const char *value)
433
471
  {
434
- file_internal *internal;
435
472
  git_config_file *file;
436
- int ret = GIT_ENOTFOUND;
437
- size_t i;
473
+ file_internal *internal;
438
474
 
439
- for (i = cfg->files.length; i > 0; --i) {
440
- internal = git_vector_get(&cfg->files, i - 1);
441
- file = internal->file;
442
- ret = file->set_multivar(file, name, regexp, value);
443
- if (ret < 0 && ret != GIT_ENOTFOUND)
444
- return ret;
445
- }
475
+ internal = git_vector_get(&cfg->files, 0);
476
+ file = internal->file;
446
477
 
447
- return 0;
478
+ return file->set_multivar(file, name, regexp, value);
448
479
  }
449
480
 
450
481
  int git_config_find_global_r(git_buf *path)
451
482
  {
452
- return git_futils_find_global_file(path, GIT_CONFIG_FILENAME);
483
+ int error = git_futils_find_global_file(path, GIT_CONFIG_FILENAME);
484
+
485
+ return error;
486
+ }
487
+
488
+ int git_config_find_xdg_r(git_buf *path)
489
+ {
490
+ int error = git_futils_find_global_file(path, GIT_CONFIG_FILENAME_ALT);
491
+
492
+ return error;
453
493
  }
454
494
 
455
495
  int git_config_find_global(char *global_config_path, size_t length)
@@ -474,6 +514,28 @@ int git_config_find_global(char *global_config_path, size_t length)
474
514
  return 0;
475
515
  }
476
516
 
517
+ int git_config_find_xdg(char *xdg_config_path, size_t length)
518
+ {
519
+ git_buf path = GIT_BUF_INIT;
520
+ int ret = git_config_find_xdg_r(&path);
521
+
522
+ if (ret < 0) {
523
+ git_buf_free(&path);
524
+ return ret;
525
+ }
526
+
527
+ if (path.size >= length) {
528
+ git_buf_free(&path);
529
+ giterr_set(GITERR_NOMEMORY,
530
+ "Path is to long to fit on the given buffer");
531
+ return -1;
532
+ }
533
+
534
+ git_buf_copy_cstr(xdg_config_path, length, &path);
535
+ git_buf_free(&path);
536
+ return 0;
537
+ }
538
+
477
539
  int git_config_find_system_r(git_buf *path)
478
540
  {
479
541
  return git_futils_find_system_file(path, GIT_CONFIG_FILENAME_SYSTEM);
@@ -501,17 +563,160 @@ int git_config_find_system(char *system_config_path, size_t length)
501
563
  return 0;
502
564
  }
503
565
 
504
- int git_config_open_global(git_config **out)
566
+ int git_config_open_default(git_config **out)
505
567
  {
506
568
  int error;
507
- git_buf path = GIT_BUF_INIT;
569
+ git_config *cfg = NULL;
570
+ git_buf buf = GIT_BUF_INIT;
508
571
 
509
- if ((error = git_config_find_global_r(&path)) < 0)
510
- return error;
572
+ error = git_config_new(&cfg);
511
573
 
512
- error = git_config_open_ondisk(out, git_buf_cstr(&path));
513
- git_buf_free(&path);
574
+ if (!error && !git_config_find_global_r(&buf))
575
+ error = git_config_add_file_ondisk(cfg, buf.ptr,
576
+ GIT_CONFIG_LEVEL_GLOBAL, 0);
577
+
578
+ if (!error && !git_config_find_xdg_r(&buf))
579
+ error = git_config_add_file_ondisk(cfg, buf.ptr,
580
+ GIT_CONFIG_LEVEL_XDG, 0);
581
+
582
+ if (!error && !git_config_find_system_r(&buf))
583
+ error = git_config_add_file_ondisk(cfg, buf.ptr,
584
+ GIT_CONFIG_LEVEL_SYSTEM, 0);
585
+
586
+ git_buf_free(&buf);
587
+
588
+ if (error && cfg) {
589
+ git_config_free(cfg);
590
+ cfg = NULL;
591
+ }
592
+
593
+ *out = cfg;
514
594
 
515
595
  return error;
516
596
  }
517
597
 
598
+ /***********
599
+ * Parsers
600
+ ***********/
601
+ int git_config_lookup_map_value(
602
+ int *out,
603
+ git_cvar_map *maps,
604
+ size_t map_n,
605
+ const char *value)
606
+ {
607
+ size_t i;
608
+
609
+ if (!value)
610
+ goto fail_parse;
611
+
612
+ for (i = 0; i < map_n; ++i) {
613
+ git_cvar_map *m = maps + i;
614
+
615
+ switch (m->cvar_type) {
616
+ case GIT_CVAR_FALSE:
617
+ case GIT_CVAR_TRUE: {
618
+ int bool_val;
619
+
620
+ if (git__parse_bool(&bool_val, value) == 0 &&
621
+ bool_val == (int)m->cvar_type) {
622
+ *out = m->map_value;
623
+ return 0;
624
+ }
625
+ break;
626
+ }
627
+
628
+ case GIT_CVAR_INT32:
629
+ if (git_config_parse_int32(out, value) == 0)
630
+ return 0;
631
+ break;
632
+
633
+ case GIT_CVAR_STRING:
634
+ if (strcasecmp(value, m->str_match) == 0) {
635
+ *out = m->map_value;
636
+ return 0;
637
+ }
638
+ break;
639
+ }
640
+ }
641
+
642
+ fail_parse:
643
+ giterr_set(GITERR_CONFIG, "Failed to map '%s'", value);
644
+ return -1;
645
+ }
646
+
647
+ int git_config_parse_bool(int *out, const char *value)
648
+ {
649
+ if (git__parse_bool(out, value) == 0)
650
+ return 0;
651
+
652
+ if (git_config_parse_int32(out, value) == 0) {
653
+ *out = !!(*out);
654
+ return 0;
655
+ }
656
+
657
+ giterr_set(GITERR_CONFIG, "Failed to parse '%s' as a boolean value", value);
658
+ return -1;
659
+ }
660
+
661
+ int git_config_parse_int64(int64_t *out, const char *value)
662
+ {
663
+ const char *num_end;
664
+ int64_t num;
665
+
666
+ if (git__strtol64(&num, value, &num_end, 0) < 0)
667
+ goto fail_parse;
668
+
669
+ switch (*num_end) {
670
+ case 'g':
671
+ case 'G':
672
+ num *= 1024;
673
+ /* fallthrough */
674
+
675
+ case 'm':
676
+ case 'M':
677
+ num *= 1024;
678
+ /* fallthrough */
679
+
680
+ case 'k':
681
+ case 'K':
682
+ num *= 1024;
683
+
684
+ /* check that that there are no more characters after the
685
+ * given modifier suffix */
686
+ if (num_end[1] != '\0')
687
+ return -1;
688
+
689
+ /* fallthrough */
690
+
691
+ case '\0':
692
+ *out = num;
693
+ return 0;
694
+
695
+ default:
696
+ goto fail_parse;
697
+ }
698
+
699
+ fail_parse:
700
+ giterr_set(GITERR_CONFIG, "Failed to parse '%s' as an integer", value);
701
+ return -1;
702
+ }
703
+
704
+ int git_config_parse_int32(int32_t *out, const char *value)
705
+ {
706
+ int64_t tmp;
707
+ int32_t truncate;
708
+
709
+ if (git_config_parse_int64(&tmp, value) < 0)
710
+ goto fail_parse;
711
+
712
+ truncate = tmp & 0xFFFFFFFF;
713
+ if (truncate != tmp)
714
+ goto fail_parse;
715
+
716
+ *out = truncate;
717
+ return 0;
718
+
719
+ fail_parse:
720
+ giterr_set(GITERR_CONFIG, "Failed to parse '%s' as a 32-bit integer", value);
721
+ return -1;
722
+ }