rugged 1.9.0 → 1.9.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (108) hide show
  1. checksums.yaml +4 -4
  2. data/ext/rugged/extconf.rb +4 -4
  3. data/ext/rugged/rugged.c +12 -1
  4. data/ext/rugged/rugged_blame.c +22 -6
  5. data/ext/rugged/rugged_blob.c +24 -9
  6. data/ext/rugged/rugged_branch.c +10 -7
  7. data/ext/rugged/rugged_branch_collection.c +8 -6
  8. data/ext/rugged/rugged_commit.c +7 -6
  9. data/ext/rugged/rugged_config.c +20 -11
  10. data/ext/rugged/rugged_diff.c +26 -12
  11. data/ext/rugged/rugged_diff_hunk.c +2 -1
  12. data/ext/rugged/rugged_index.c +39 -29
  13. data/ext/rugged/rugged_note.c +7 -6
  14. data/ext/rugged/rugged_object.c +3 -2
  15. data/ext/rugged/rugged_patch.c +23 -9
  16. data/ext/rugged/rugged_rebase.c +22 -10
  17. data/ext/rugged/rugged_reference.c +22 -13
  18. data/ext/rugged/rugged_reference_collection.c +9 -7
  19. data/ext/rugged/rugged_remote.c +23 -12
  20. data/ext/rugged/rugged_remote_collection.c +11 -9
  21. data/ext/rugged/rugged_repo.c +60 -45
  22. data/ext/rugged/rugged_revwalk.c +22 -12
  23. data/ext/rugged/rugged_submodule.c +23 -20
  24. data/ext/rugged/rugged_submodule_collection.c +20 -9
  25. data/ext/rugged/rugged_tag.c +6 -4
  26. data/ext/rugged/rugged_tag_collection.c +7 -5
  27. data/ext/rugged/rugged_tree.c +27 -15
  28. data/lib/rugged/version.rb +1 -1
  29. data/vendor/libgit2/AUTHORS +2 -0
  30. data/vendor/libgit2/CMakeLists.txt +1 -1
  31. data/vendor/libgit2/cmake/DefaultCFlags.cmake +4 -1
  32. data/vendor/libgit2/cmake/SelectSSH.cmake +9 -3
  33. data/vendor/libgit2/deps/pcre/CMakeLists.txt +2 -3
  34. data/vendor/libgit2/deps/xdiff/CMakeLists.txt +1 -1
  35. data/vendor/libgit2/deps/xdiff/xmerge.c +14 -10
  36. data/vendor/libgit2/include/git2/deprecated.h +1 -1
  37. data/vendor/libgit2/include/git2/index.h +1 -1
  38. data/vendor/libgit2/include/git2/merge.h +4 -2
  39. data/vendor/libgit2/include/git2/oid.h +0 -1
  40. data/vendor/libgit2/include/git2/proxy.h +2 -3
  41. data/vendor/libgit2/include/git2/remote.h +19 -7
  42. data/vendor/libgit2/include/git2/stdint.h +1 -1
  43. data/vendor/libgit2/include/git2/sys/transport.h +1 -1
  44. data/vendor/libgit2/include/git2/version.h +4 -2
  45. data/vendor/libgit2/src/cli/CMakeLists.txt +1 -2
  46. data/vendor/libgit2/src/cli/opt.c +3 -3
  47. data/vendor/libgit2/src/cli/opt_usage.c +1 -1
  48. data/vendor/libgit2/src/libgit2/CMakeLists.txt +32 -16
  49. data/vendor/libgit2/src/libgit2/attr_file.c +10 -3
  50. data/vendor/libgit2/src/libgit2/clone.c +6 -0
  51. data/vendor/libgit2/src/libgit2/commit.c +1 -1
  52. data/vendor/libgit2/src/libgit2/commit_graph.c +1 -2
  53. data/vendor/libgit2/src/libgit2/config.c +1 -1
  54. data/vendor/libgit2/src/libgit2/config_file.c +2 -1
  55. data/vendor/libgit2/src/libgit2/config_mem.c +1 -0
  56. data/vendor/libgit2/src/libgit2/config_parse.c +2 -1
  57. data/vendor/libgit2/src/libgit2/delta.c +5 -1
  58. data/vendor/libgit2/src/libgit2/diff_driver.c +1 -1
  59. data/vendor/libgit2/src/libgit2/diff_stats.c +19 -12
  60. data/vendor/libgit2/src/libgit2/fetchhead.c +1 -1
  61. data/vendor/libgit2/src/libgit2/index.c +8 -8
  62. data/vendor/libgit2/src/libgit2/index.h +3 -0
  63. data/vendor/libgit2/src/libgit2/indexer.c +2 -2
  64. data/vendor/libgit2/src/libgit2/merge.c +1 -1
  65. data/vendor/libgit2/src/libgit2/merge.h +4 -0
  66. data/vendor/libgit2/src/libgit2/merge_file.c +43 -30
  67. data/vendor/libgit2/src/libgit2/message.c +1 -1
  68. data/vendor/libgit2/src/libgit2/midx.c +2 -3
  69. data/vendor/libgit2/src/libgit2/odb.c +2 -6
  70. data/vendor/libgit2/src/libgit2/odb_loose.c +24 -14
  71. data/vendor/libgit2/src/libgit2/oid.c +4 -5
  72. data/vendor/libgit2/src/libgit2/pack-objects.c +2 -4
  73. data/vendor/libgit2/src/libgit2/pack.c +3 -0
  74. data/vendor/libgit2/src/libgit2/refs.c +15 -6
  75. data/vendor/libgit2/src/libgit2/remote.c +4 -1
  76. data/vendor/libgit2/src/libgit2/remote.h +0 -1
  77. data/vendor/libgit2/src/libgit2/repository.c +5 -4
  78. data/vendor/libgit2/src/libgit2/streams/socket.c +30 -0
  79. data/vendor/libgit2/src/libgit2/submodule.c +12 -5
  80. data/vendor/libgit2/src/libgit2/tag.c +3 -1
  81. data/vendor/libgit2/src/libgit2/transports/auth_sspi.c +2 -0
  82. data/vendor/libgit2/src/libgit2/transports/credential.c +1 -1
  83. data/vendor/libgit2/src/libgit2/transports/git.c +1 -1
  84. data/vendor/libgit2/src/libgit2/transports/httpclient.c +12 -9
  85. data/vendor/libgit2/src/libgit2/transports/local.c +8 -1
  86. data/vendor/libgit2/src/libgit2/transports/smart.c +5 -5
  87. data/vendor/libgit2/src/libgit2/transports/smart_pkt.c +3 -3
  88. data/vendor/libgit2/src/libgit2/transports/ssh_exec.c +57 -18
  89. data/vendor/libgit2/src/libgit2/transports/ssh_libssh2.c +3 -3
  90. data/vendor/libgit2/src/util/CMakeLists.txt +3 -4
  91. data/vendor/libgit2/src/util/fs_path.c +66 -6
  92. data/vendor/libgit2/src/util/fs_path.h +6 -0
  93. data/vendor/libgit2/src/util/futils.h +11 -3
  94. data/vendor/libgit2/src/util/hash/builtin.c +14 -4
  95. data/vendor/libgit2/src/util/hash/openssl.c +0 -4
  96. data/vendor/libgit2/src/util/hash/rfc6234/sha224-256.c +8 -6
  97. data/vendor/libgit2/src/util/hashmap.h +1 -0
  98. data/vendor/libgit2/src/util/net.c +5 -5
  99. data/vendor/libgit2/src/util/process.h +2 -1
  100. data/vendor/libgit2/src/util/runtime.c +2 -2
  101. data/vendor/libgit2/src/util/str.c +18 -6
  102. data/vendor/libgit2/src/util/str.h +5 -3
  103. data/vendor/libgit2/src/util/unix/process.c +92 -15
  104. data/vendor/libgit2/src/util/util.c +16 -3
  105. data/vendor/libgit2/src/util/util.h +1 -0
  106. data/vendor/libgit2/src/util/win32/path_w32.c +81 -5
  107. data/vendor/libgit2/src/util/win32/process.c +22 -6
  108. metadata +17 -6
@@ -161,7 +161,7 @@ static void ssh_custom_free(struct git_credential *cred)
161
161
 
162
162
  if (c->publickey) {
163
163
  /* Zero the memory which previously held the publickey */
164
- size_t key_len = strlen(c->publickey);
164
+ size_t key_len = c->publickey_len;
165
165
  git__memzero(c->publickey, key_len);
166
166
  git__free(c->publickey);
167
167
  }
@@ -39,7 +39,7 @@ typedef struct {
39
39
  */
40
40
  static int gen_proto(git_str *request, const char *cmd, const char *url)
41
41
  {
42
- char *delim, *repo;
42
+ const char *delim, *repo;
43
43
  char host[] = "host=";
44
44
  size_t len;
45
45
 
@@ -379,7 +379,7 @@ static int on_headers_complete(git_http_parser *parser)
379
379
  ctx->response->resend_credentials = resend_needed(ctx->client,
380
380
  ctx->response);
381
381
 
382
- if (ctx->response->content_type || ctx->response->chunked)
382
+ if (ctx->response->content_length || ctx->response->chunked)
383
383
  ctx->client->state = READING_BODY;
384
384
  else
385
385
  ctx->client->state = DONE;
@@ -553,7 +553,7 @@ static int apply_credentials(
553
553
  {
554
554
  git_http_auth_context *auth = server->auth_context;
555
555
  git_vector *challenges = &server->auth_challenges;
556
- const char *challenge;
556
+ const char *challenge = NULL;
557
557
  git_str token = GIT_STR_INIT;
558
558
  int error = 0;
559
559
 
@@ -1243,13 +1243,16 @@ GIT_INLINE(int) client_read_and_parse(git_http_client *client)
1243
1243
  }
1244
1244
 
1245
1245
  /*
1246
- * See if we've consumed the entire response body. If the client was
1247
- * reading the body but did not consume it entirely, it's possible that
1248
- * they knew that the stream had finished (in a git response, seeing a
1249
- * final flush) and stopped reading. But if the response was chunked,
1250
- * we may have not consumed the final chunk marker. Consume it to
1251
- * ensure that we don't have it waiting in our socket. If there's
1252
- * more than just a chunk marker, close the connection.
1246
+ * Try to consume any remaining response body. The client may have
1247
+ * decided that it did not need to consume the entire response body.
1248
+ * For example, the client saw a redirect in the header and ignored
1249
+ * the body. Or the client saw a particular sequence (like a final
1250
+ * flush in a git response) and stopped reading (but there were
1251
+ * additional response bytes, perhaps because the response was chunked).
1252
+ * Do one more read to try to clear this out; this takes care of small
1253
+ * remainders, like a chunk response or a small redirect message. If
1254
+ * there is too much data, we'll just leave it and close the
1255
+ * connection.
1253
1256
  */
1254
1257
  static void complete_response_body(git_http_client *client)
1255
1258
  {
@@ -41,6 +41,9 @@ typedef struct {
41
41
  git_vector refs;
42
42
  unsigned connected : 1,
43
43
  have_refs : 1;
44
+ #ifdef GIT_EXPERIMENTAL_SHA256
45
+ git_oid_t oid_type;
46
+ #endif
44
47
  } transport_local;
45
48
 
46
49
  static void free_head(git_remote_head *head)
@@ -231,6 +234,10 @@ static int local_connect(
231
234
 
232
235
  t->repo = repo;
233
236
 
237
+ #ifdef GIT_EXPERIMENTAL_SHA256
238
+ t->oid_type = repo->oid_type;
239
+ #endif
240
+
234
241
  if (store_refs(t) < 0)
235
242
  return -1;
236
243
 
@@ -267,7 +274,7 @@ static int local_oid_type(git_oid_t *out, git_transport *transport)
267
274
  {
268
275
  transport_local *t = (transport_local *)transport;
269
276
 
270
- *out = t->repo->oid_type;
277
+ *out = t->oid_type;
271
278
 
272
279
  return 0;
273
280
  }
@@ -64,13 +64,13 @@ GIT_INLINE(int) git_smart__reset_stream(transport_smart *t, bool close_subtransp
64
64
 
65
65
  if (t->wrapped->close(t->wrapped) < 0)
66
66
  return -1;
67
- }
68
67
 
69
- git__free(t->caps.object_format);
70
- t->caps.object_format = NULL;
68
+ git__free(t->caps.object_format);
69
+ t->caps.object_format = NULL;
71
70
 
72
- git__free(t->caps.agent);
73
- t->caps.agent = NULL;
71
+ git__free(t->caps.agent);
72
+ t->caps.agent = NULL;
73
+ }
74
74
 
75
75
  return 0;
76
76
  }
@@ -238,13 +238,13 @@ static int set_data(
238
238
 
239
239
  if (strncmp(caps, "object-format=", CONST_STRLEN("object-format=")) == 0)
240
240
  format_str = caps + CONST_STRLEN("object-format=");
241
- else if ((format_str = strstr(caps, " object-format=")) != NULL)
241
+ else if ((format_str = git__memmem(caps, len - (caps - line), " object-format=", CONST_STRLEN(" object-format="))) != NULL)
242
242
  format_str += CONST_STRLEN(" object-format=");
243
243
  }
244
244
 
245
245
  if (format_str) {
246
- if ((eos = strchr(format_str, ' ')) == NULL)
247
- eos = strchr(format_str, '\0');
246
+ if ((eos = memchr(format_str, ' ', len - (format_str - line))) == NULL)
247
+ eos = memchr(format_str, '\0', len - (format_str - line));
248
248
 
249
249
  GIT_ASSERT(eos);
250
250
 
@@ -120,7 +120,8 @@ GIT_INLINE(int) ensure_transport_state(
120
120
  }
121
121
 
122
122
  static int get_ssh_cmdline(
123
- git_str *out,
123
+ git_vector *args,
124
+ bool *use_shell,
124
125
  ssh_exec_subtransport *transport,
125
126
  git_net_url *url,
126
127
  const char *command)
@@ -128,7 +129,8 @@ static int get_ssh_cmdline(
128
129
  git_remote *remote = ((transport_smart *)transport->owner)->owner;
129
130
  git_repository *repo = remote->repo;
130
131
  git_config *cfg;
131
- git_str ssh_cmd = GIT_STR_INIT;
132
+ git_str ssh_cmd = GIT_STR_INIT, url_and_host = GIT_STR_INIT,
133
+ remote_cmd = GIT_STR_INIT;
132
134
  const char *default_ssh_cmd = "ssh";
133
135
  int error;
134
136
 
@@ -151,25 +153,57 @@ static int get_ssh_cmdline(
151
153
  if ((error = git_repository_config_snapshot(&cfg, repo)) < 0)
152
154
  return error;
153
155
 
154
- if ((error = git__getenv(&ssh_cmd, "GIT_SSH")) == 0)
155
- ;
156
+ if ((error = git__getenv(&ssh_cmd, "GIT_SSH_COMMAND")) == 0)
157
+ *use_shell = true;
158
+ else if (error != GIT_ENOTFOUND)
159
+ goto done;
160
+ else if ((error = git__getenv(&ssh_cmd, "GIT_SSH")) == 0)
161
+ *use_shell = false;
156
162
  else if (error != GIT_ENOTFOUND)
157
163
  goto done;
158
164
  else if ((error = git_config__get_string_buf(&ssh_cmd, cfg, "core.sshcommand")) < 0 && error != GIT_ENOTFOUND)
159
165
  goto done;
160
166
 
161
- error = git_str_printf(out, "%s %s %s \"%s%s%s\" \"%s\" \"%s\"",
162
- ssh_cmd.size > 0 ? ssh_cmd.ptr : default_ssh_cmd,
163
- url->port_specified ? "-p" : "",
164
- url->port_specified ? url->port : "",
165
- url->username ? url->username : "",
166
- url->username ? "@" : "",
167
- url->host,
168
- command,
169
- url->path);
167
+ git_error_clear();
168
+
169
+ if (!ssh_cmd.size &&
170
+ git_str_puts(&ssh_cmd, default_ssh_cmd) < 0)
171
+ goto done;
172
+
173
+ if ((error = git_vector_insert(args, git_str_detach(&ssh_cmd))) < 0)
174
+ goto done;
175
+
176
+ if (url->port_specified) {
177
+ char *p = git__strdup("-p");
178
+ char *port = git__strdup(url->port);
179
+
180
+ if (!p || !port ||
181
+ (error = git_vector_insert(args, p)) < 0 ||
182
+ (error = git_vector_insert(args, port)) < 0)
183
+ goto done;
184
+ }
185
+
186
+ if (url->username) {
187
+ if ((error = git_str_puts(&url_and_host, url->username)) < 0 ||
188
+ (error = git_str_putc(&url_and_host, '@')) < 0)
189
+ goto done;
190
+ }
191
+
192
+ if ((error = git_str_puts(&url_and_host, url->host)) < 0 ||
193
+ (error = git_vector_insert(args, git_str_detach(&url_and_host))) < 0)
194
+ goto done;
195
+
196
+ if ((error = git_str_puts(&remote_cmd, command)) < 0 ||
197
+ (error = git_str_puts(&remote_cmd, " '")) < 0 ||
198
+ (error = git_str_puts_escaped(&remote_cmd, url->path, "'!", "'\\", "'")) < 0 ||
199
+ (error = git_str_puts(&remote_cmd, "'")) < 0 ||
200
+ (error = git_vector_insert(args, git_str_detach(&remote_cmd))) < 0)
201
+ goto done;
170
202
 
171
203
  done:
172
204
  git_str_dispose(&ssh_cmd);
205
+ git_str_dispose(&url_and_host);
206
+ git_str_dispose(&remote_cmd);
173
207
  git_config_free(cfg);
174
208
  return error;
175
209
  }
@@ -183,7 +217,8 @@ static int start_ssh(
183
217
 
184
218
  git_process_options process_opts = GIT_PROCESS_OPTIONS_INIT;
185
219
  git_net_url url = GIT_NET_URL_INIT;
186
- git_str ssh_cmdline = GIT_STR_INIT;
220
+ git_vector args = GIT_VECTOR_INIT;
221
+ bool use_shell = false;
187
222
  const char *command;
188
223
  int error;
189
224
 
@@ -214,11 +249,15 @@ static int start_ssh(
214
249
  if (error < 0)
215
250
  goto done;
216
251
 
217
- if ((error = get_ssh_cmdline(&ssh_cmdline, transport, &url, command)) < 0)
252
+ if ((error = get_ssh_cmdline(&args, &use_shell,
253
+ transport, &url, command)) < 0)
218
254
  goto done;
219
255
 
220
- if ((error = git_process_new_from_cmdline(&transport->process,
221
- ssh_cmdline.ptr, env, ARRAY_SIZE(env), &process_opts)) < 0 ||
256
+ process_opts.use_shell = use_shell;
257
+
258
+ if ((error = git_process_new(&transport->process,
259
+ (const char **)args.contents, args.length,
260
+ env, ARRAY_SIZE(env), &process_opts)) < 0 ||
222
261
  (error = git_process_start(transport->process)) < 0) {
223
262
  git_process_free(transport->process);
224
263
  transport->process = NULL;
@@ -226,7 +265,7 @@ static int start_ssh(
226
265
  }
227
266
 
228
267
  done:
229
- git_str_dispose(&ssh_cmdline);
268
+ git_vector_dispose_deep(&args);
230
269
  git_net_url_dispose(&url);
231
270
  return error;
232
271
  }
@@ -366,7 +366,7 @@ static int _git_ssh_authenticate_session(
366
366
  default:
367
367
  rc = LIBSSH2_ERROR_AUTHENTICATION_FAILED;
368
368
  }
369
- } while (LIBSSH2_ERROR_EAGAIN == rc || LIBSSH2_ERROR_TIMEOUT == rc);
369
+ } while (LIBSSH2_ERROR_EAGAIN == rc);
370
370
 
371
371
  if (rc == LIBSSH2_ERROR_PASSWORD_EXPIRED ||
372
372
  rc == LIBSSH2_ERROR_AUTHENTICATION_FAILED ||
@@ -556,7 +556,7 @@ static int _git_ssh_session_create(
556
556
  if (git_str_len(&prefs) > 0) {
557
557
  do {
558
558
  rc = libssh2_session_method_pref(s, LIBSSH2_METHOD_HOSTKEY, git_str_cstr(&prefs));
559
- } while (LIBSSH2_ERROR_EAGAIN == rc || LIBSSH2_ERROR_TIMEOUT == rc);
559
+ } while (LIBSSH2_ERROR_EAGAIN == rc);
560
560
  if (rc != LIBSSH2_ERROR_NONE) {
561
561
  ssh_error(s, "failed to set hostkey preference");
562
562
  goto on_error;
@@ -566,7 +566,7 @@ static int _git_ssh_session_create(
566
566
 
567
567
  do {
568
568
  rc = libssh2_session_handshake(s, socket->s);
569
- } while (LIBSSH2_ERROR_EAGAIN == rc || LIBSSH2_ERROR_TIMEOUT == rc);
569
+ } while (LIBSSH2_ERROR_EAGAIN == rc);
570
570
 
571
571
  if (rc != LIBSSH2_ERROR_NONE) {
572
572
  ssh_error(s, "failed to start SSH session");
@@ -2,13 +2,12 @@
2
2
 
3
3
  add_library(util OBJECT)
4
4
 
5
- configure_file(git2_features.h.in git2_features.h)
5
+ configure_file(git2_features.h.in "${PROJECT_BINARY_DIR}/gen_headers/git2_features.h")
6
6
 
7
7
  set(UTIL_INCLUDES
8
- "${PROJECT_BINARY_DIR}/src/util"
9
- "${PROJECT_BINARY_DIR}/include"
10
8
  "${PROJECT_SOURCE_DIR}/src/util"
11
- "${PROJECT_SOURCE_DIR}/include")
9
+ "${PROJECT_SOURCE_DIR}/include"
10
+ "${PROJECT_BINARY_DIR}/gen_headers")
12
11
 
13
12
  file(GLOB UTIL_SRC *.c *.h allocators/*.c allocators/*.h hash.h)
14
13
  list(SORT UTIL_SRC)
@@ -611,6 +611,37 @@ bool git_fs_path_isfile(const char *path)
611
611
  return S_ISREG(st.st_mode) != 0;
612
612
  }
613
613
 
614
+ #ifdef GIT_WIN32
615
+
616
+ bool git_fs_path_isexecutable(const char *path)
617
+ {
618
+ struct stat st;
619
+
620
+ GIT_ASSERT_ARG_WITH_RETVAL(path, false);
621
+
622
+ if (git__suffixcmp_icase(path, ".exe") != 0 &&
623
+ git__suffixcmp_icase(path, ".cmd") != 0)
624
+ return false;
625
+
626
+ return (p_stat(path, &st) == 0);
627
+ }
628
+
629
+ #else
630
+
631
+ bool git_fs_path_isexecutable(const char *path)
632
+ {
633
+ struct stat st;
634
+
635
+ GIT_ASSERT_ARG_WITH_RETVAL(path, false);
636
+ if (p_stat(path, &st) < 0)
637
+ return false;
638
+
639
+ return S_ISREG(st.st_mode) != 0 &&
640
+ ((st.st_mode & S_IXUSR) != 0);
641
+ }
642
+
643
+ #endif
644
+
614
645
  bool git_fs_path_islink(const char *path)
615
646
  {
616
647
  struct stat st;
@@ -2020,9 +2051,10 @@ int git_fs_path_owner_is_system(bool *out, const char *path)
2020
2051
  return git_fs_path_owner_is(out, path, GIT_FS_PATH_OWNER_ADMINISTRATOR);
2021
2052
  }
2022
2053
 
2023
- int git_fs_path_find_executable(git_str *fullpath, const char *executable)
2024
- {
2025
2054
  #ifdef GIT_WIN32
2055
+
2056
+ static int find_executable(git_str *fullpath, const char *executable)
2057
+ {
2026
2058
  git_win32_path fullpath_w, executable_w;
2027
2059
  int error;
2028
2060
 
@@ -2035,9 +2067,15 @@ int git_fs_path_find_executable(git_str *fullpath, const char *executable)
2035
2067
  error = git_str_put_w(fullpath, fullpath_w, wcslen(fullpath_w));
2036
2068
 
2037
2069
  return error;
2070
+ }
2071
+
2038
2072
  #else
2073
+
2074
+ static int find_executable(git_str *fullpath, const char *executable)
2075
+ {
2039
2076
  git_str path = GIT_STR_INIT;
2040
2077
  const char *current_dir, *term;
2078
+ size_t current_dirlen;
2041
2079
  bool found = false;
2042
2080
 
2043
2081
  if (git__getenv(&path, "PATH") < 0)
@@ -2049,20 +2087,28 @@ int git_fs_path_find_executable(git_str *fullpath, const char *executable)
2049
2087
  if (! (term = strchr(current_dir, GIT_PATH_LIST_SEPARATOR)))
2050
2088
  term = strchr(current_dir, '\0');
2051
2089
 
2090
+ current_dirlen = term - current_dir;
2052
2091
  git_str_clear(fullpath);
2053
- if (git_str_put(fullpath, current_dir, (term - current_dir)) < 0 ||
2054
- git_str_putc(fullpath, '/') < 0 ||
2092
+
2093
+ /* An empty path segment is treated as '.' */
2094
+ if (current_dirlen == 0 && git_str_putc(fullpath, '.'))
2095
+ return -1;
2096
+ else if (current_dirlen != 0 &&
2097
+ git_str_put(fullpath, current_dir, current_dirlen) < 0)
2098
+ return -1;
2099
+
2100
+ if (git_str_putc(fullpath, '/') < 0 ||
2055
2101
  git_str_puts(fullpath, executable) < 0)
2056
2102
  return -1;
2057
2103
 
2058
- if (git_fs_path_isfile(fullpath->ptr)) {
2104
+ if (git_fs_path_isexecutable(fullpath->ptr)) {
2059
2105
  found = true;
2060
2106
  break;
2061
2107
  }
2062
2108
 
2063
2109
  current_dir = term;
2064
2110
 
2065
- while (*current_dir == GIT_PATH_LIST_SEPARATOR)
2111
+ if (*current_dir == GIT_PATH_LIST_SEPARATOR)
2066
2112
  current_dir++;
2067
2113
  }
2068
2114
 
@@ -2073,5 +2119,19 @@ int git_fs_path_find_executable(git_str *fullpath, const char *executable)
2073
2119
 
2074
2120
  git_str_clear(fullpath);
2075
2121
  return GIT_ENOTFOUND;
2122
+ }
2123
+
2076
2124
  #endif
2125
+
2126
+ int git_fs_path_find_executable(git_str *fullpath, const char *executable)
2127
+ {
2128
+ /* For qualified paths we do not look in PATH */
2129
+ if (strchr(executable, '/') != NULL) {
2130
+ if (!git_fs_path_isexecutable(executable))
2131
+ return GIT_ENOTFOUND;
2132
+
2133
+ return git_str_puts(fullpath, executable);
2134
+ }
2135
+
2136
+ return find_executable(fullpath, executable);
2077
2137
  }
@@ -204,6 +204,12 @@ extern bool git_fs_path_isdir(const char *path);
204
204
  */
205
205
  extern bool git_fs_path_isfile(const char *path);
206
206
 
207
+ /**
208
+ * Check if the given path points to an executable.
209
+ * @return true or false
210
+ */
211
+ extern bool git_fs_path_isexecutable(const char *path);
212
+
207
213
  /**
208
214
  * Check if the given path points to a symbolic link.
209
215
  * @return true or false
@@ -32,9 +32,17 @@ extern int git_futils_readbuffer_fd(git_str *obj, git_file fd, size_t len);
32
32
 
33
33
  /* Additional constants for `git_futils_writebuffer`'s `open_flags`. We
34
34
  * support these internally and they will be removed before the `open` call.
35
- */
36
- #ifndef O_FSYNC
37
- # define O_FSYNC (1 << 31)
35
+ *
36
+ * Not all platforms define O_FSYNC. Fall back to O_SYNC (the POSIX
37
+ * standard name; O_FSYNC is a non-standard alias) when available,
38
+ * otherwise use a sentinel value that won't collide with real open
39
+ * flags. Avoid (1 << 31) since left-shifting into the sign bit of
40
+ * a signed int is undefined behavior.
41
+ */
42
+ #if !defined(O_FSYNC) && defined(O_SYNC)
43
+ # define O_FSYNC O_SYNC
44
+ #elif !defined(O_FSYNC)
45
+ # define O_FSYNC (1 << 30)
38
46
  #endif
39
47
 
40
48
  extern int git_futils_writebuffer(
@@ -32,13 +32,23 @@ int git_hash_sha256_init(git_hash_sha256_ctx *ctx)
32
32
  return 0;
33
33
  }
34
34
 
35
- int git_hash_sha256_update(git_hash_sha256_ctx *ctx, const void *data, size_t len)
35
+ int git_hash_sha256_update(git_hash_sha256_ctx *ctx, const void *_data, size_t len)
36
36
  {
37
+ const unsigned char *data = _data;
37
38
  GIT_ASSERT_ARG(ctx);
38
- if (SHA256Input(&ctx->c, data, len)) {
39
- git_error_set(GIT_ERROR_SHA, "SHA256 error");
40
- return -1;
39
+
40
+ while (len > 0) {
41
+ unsigned int chunk = (len > UINT_MAX) ? UINT_MAX : (unsigned int)len;
42
+
43
+ if (SHA256Input(&ctx->c, data, chunk)) {
44
+ git_error_set(GIT_ERROR_SHA, "SHA256 error");
45
+ return -1;
46
+ }
47
+
48
+ data += chunk;
49
+ len -= chunk;
41
50
  }
51
+
42
52
  return 0;
43
53
  }
44
54
 
@@ -189,8 +189,6 @@ int git_hash_sha1_final(unsigned char *out, git_hash_sha1_ctx *ctx)
189
189
  return -1;
190
190
  }
191
191
 
192
- ctx->c = NULL;
193
-
194
192
  return 0;
195
193
  }
196
194
 
@@ -339,8 +337,6 @@ int git_hash_sha256_final(unsigned char *out, git_hash_sha256_ctx *ctx)
339
337
  return -1;
340
338
  }
341
339
 
342
- ctx->c = NULL;
343
-
344
340
  return 0;
345
341
  }
346
342
 
@@ -83,12 +83,14 @@
83
83
  * Add "length" to the length.
84
84
  * Set Corrupted when overflow has occurred.
85
85
  */
86
- static uint32_t addTemp;
87
- #define SHA224_256AddLength(context, length) \
88
- (addTemp = (context)->Length_Low, (context)->Corrupted = \
89
- (((context)->Length_Low += (length)) < addTemp) && \
90
- (++(context)->Length_High == 0) ? shaInputTooLong : \
91
- (context)->Corrupted )
86
+ static int SHA224_256AddLength(SHA256Context *context, unsigned int length)
87
+ {
88
+ uint32_t addTemp = context->Length_Low;
89
+ context->Length_Low += length;
90
+ if (context->Length_Low < addTemp && ++context->Length_High == 0)
91
+ context->Corrupted = shaInputTooLong;
92
+ return context->Corrupted;
93
+ }
92
94
 
93
95
  /* Local Function Prototypes */
94
96
  static int SHA224_256Reset(SHA256Context *context, uint32_t *H0);
@@ -107,6 +107,7 @@ typedef uint32_t git_hashmap_iter_t;
107
107
  } \
108
108
  GIT_INLINE(int) name##__idx(uint32_t *out, name *h, key_t key) \
109
109
  { \
110
+ *out = UINT32_MAX; \
110
111
  if (h->n_buckets) { \
111
112
  uint32_t k, i, last, mask, step = 0; \
112
113
  GIT_ASSERT((h)->flags); \
@@ -184,8 +184,8 @@ static int url_parse_authority(
184
184
  const char *authority,
185
185
  size_t len)
186
186
  {
187
- const char *c, *hostport_end, *host_end = NULL,
188
- *userpass_end, *user_end = NULL;
187
+ const char *c, *hostport_end = NULL, *host_end = NULL,
188
+ *userpass_end = NULL, *user_end = NULL;
189
189
 
190
190
  enum {
191
191
  HOSTPORT, HOST, IPV6, HOST_END, USERPASS, USER
@@ -464,7 +464,7 @@ done:
464
464
  int git_net_url_parse(git_net_url *url, const char *given)
465
465
  {
466
466
  git_net_url_parser parser = GIT_NET_URL_PARSER_INIT;
467
- const char *c, *authority, *path;
467
+ const char *c, *authority = NULL, *path = NULL;
468
468
  size_t authority_len = 0, path_len = 0;
469
469
  int error = 0;
470
470
 
@@ -574,7 +574,7 @@ int git_net_url_parse_http(
574
574
  const char *given)
575
575
  {
576
576
  git_net_url_parser parser = GIT_NET_URL_PARSER_INIT;
577
- const char *c, *authority, *path = NULL;
577
+ const char *c = NULL, *authority = NULL, *path = NULL;
578
578
  size_t authority_len = 0, path_len = 0;
579
579
  int error;
580
580
 
@@ -661,7 +661,7 @@ static bool has_at(const char *str)
661
661
  int git_net_url_parse_scp(git_net_url *url, const char *given)
662
662
  {
663
663
  const char *default_port = default_port_for_scheme("ssh");
664
- const char *c, *user, *host, *port = NULL, *path = NULL;
664
+ const char *c, *user = NULL, *host = NULL, *port = NULL, *path = NULL;
665
665
  size_t user_len = 0, host_len = 0, port_len = 0;
666
666
  unsigned short bracket = 0;
667
667
 
@@ -11,7 +11,8 @@
11
11
  typedef struct git_process git_process;
12
12
 
13
13
  typedef struct {
14
- unsigned int capture_in : 1,
14
+ unsigned int use_shell : 1,
15
+ capture_in : 1,
15
16
  capture_out : 1,
16
17
  capture_err : 1,
17
18
  exclude_env : 1;
@@ -16,7 +16,7 @@ static git_atomic32 init_count;
16
16
  static int init_common(git_runtime_init_fn init_fns[], size_t cnt)
17
17
  {
18
18
  size_t i;
19
- int ret;
19
+ int ret = 0;
20
20
 
21
21
  /* Initialize subsystems that have global state */
22
22
  for (i = 0; i < cnt; i++) {
@@ -110,7 +110,7 @@ GIT_INLINE(int) init_unlock(void)
110
110
 
111
111
  int git_runtime_init(git_runtime_init_fn init_fns[], size_t cnt)
112
112
  {
113
- int ret;
113
+ int ret = 0;
114
114
 
115
115
  if (init_lock() < 0)
116
116
  return -1;
@@ -1065,10 +1065,13 @@ int git_str_puts_escaped(
1065
1065
  git_str *buf,
1066
1066
  const char *string,
1067
1067
  const char *esc_chars,
1068
- const char *esc_with)
1068
+ const char *esc_prefix,
1069
+ const char *esc_suffix)
1069
1070
  {
1070
1071
  const char *scan;
1071
- size_t total = 0, esc_len = strlen(esc_with), count, alloclen;
1072
+ size_t total = 0, count, alloclen;
1073
+ size_t esc_prefix_len = esc_prefix ? strlen(esc_prefix) : 0;
1074
+ size_t esc_suffix_len = esc_suffix ? strlen(esc_suffix) : 0;
1072
1075
 
1073
1076
  if (!string)
1074
1077
  return 0;
@@ -1080,7 +1083,7 @@ int git_str_puts_escaped(
1080
1083
  scan += count;
1081
1084
  /* count run of escaped characters */
1082
1085
  count = strspn(scan, esc_chars);
1083
- total += count * (esc_len + 1);
1086
+ total += count * (esc_prefix_len + esc_suffix_len + 1);
1084
1087
  scan += count;
1085
1088
  }
1086
1089
 
@@ -1096,13 +1099,22 @@ int git_str_puts_escaped(
1096
1099
  buf->size += count;
1097
1100
 
1098
1101
  for (count = strspn(scan, esc_chars); count > 0; --count) {
1099
- /* copy escape sequence */
1100
- memmove(buf->ptr + buf->size, esc_with, esc_len);
1101
- buf->size += esc_len;
1102
+ /* copy escape prefix sequence */
1103
+ if (esc_prefix) {
1104
+ memmove(buf->ptr + buf->size, esc_prefix, esc_prefix_len);
1105
+ buf->size += esc_prefix_len;
1106
+ }
1107
+
1102
1108
  /* copy character to be escaped */
1103
1109
  buf->ptr[buf->size] = *scan;
1104
1110
  buf->size++;
1105
1111
  scan++;
1112
+
1113
+ /* copy escape suffix sequence */
1114
+ if (esc_suffix) {
1115
+ memmove(buf->ptr + buf->size, esc_suffix, esc_suffix_len);
1116
+ buf->size += esc_suffix_len;
1117
+ }
1106
1118
  }
1107
1119
  }
1108
1120