Example #1
0
int index_pack(git_repository *repo, int argc, char **argv)
{
  git_indexer_stream *idx;
  git_indexer_stats stats = {0, 0};
  int error, fd;
  char hash[GIT_OID_HEXSZ + 1] = {0};
  ssize_t read_bytes;
  char buf[512];

  if (argc < 2) {
	  fprintf(stderr, "I need a packfile\n");
	  return EXIT_FAILURE;
  }

  if (git_indexer_stream_new(&idx, ".git") < 0) {
	  puts("bad idx");
	  return -1;
  }

  if ((fd = open(argv[1], 0)) < 0) {
	  perror("open");
	  return -1;
  }

  do {
	  read_bytes = read(fd, buf, sizeof(buf));
	  if (read_bytes < 0)
		  break;

	  if ((error = git_indexer_stream_add(idx, buf, read_bytes, &stats)) < 0)
		  goto cleanup;

	  printf("\rIndexing %d of %d", stats.processed, stats.total);
  } while (read_bytes > 0);

  if (read_bytes < 0) {
	  error = -1;
	  perror("failed reading");
	  goto cleanup;
  }

  if ((error = git_indexer_stream_finalize(idx, &stats)) < 0)
	  goto cleanup;

  printf("\rIndexing %d of %d\n", stats.processed, stats.total);

  git_oid_fmt(hash, git_indexer_stream_hash(idx));
  puts(hash);

cleanup:
  close(fd);
  git_indexer_stream_free(idx);
  return error;
}
Example #2
0
/*
 * As the server is probably using Transfer-Encoding: chunked, we have
 * to use the HTTP parser to download the pack instead of giving it to
 * the simple downloader. Furthermore, we're using keep-alive
 * connections, so the simple downloader would just hang.
 */
static int http_download_pack(git_transport *transport, git_repository *repo, git_off_t *bytes, git_indexer_stats *stats)
{
	transport_http *t = (transport_http *) transport;
	git_buf *oldbuf = &t->buf;
	int recvd;
	http_parser_settings settings;
	char buffer[1024];
	gitno_buffer buf;
	git_buf path = GIT_BUF_INIT;
	git_indexer_stream *idx = NULL;
	download_pack_cbdata data;

	gitno_buffer_setup(transport, &buf, buffer, sizeof(buffer));

	if (memcmp(oldbuf->ptr, "PACK", strlen("PACK"))) {
		giterr_set(GITERR_NET, "The pack doesn't start with a pack signature");
		return -1;
	}

	if (git_buf_joinpath(&path, git_repository_path(repo), "objects/pack") < 0)
		return -1;

	if (git_indexer_stream_new(&idx, git_buf_cstr(&path)) < 0)
		return -1;

	/*
	 * This is part of the previous response, so we don't want to
	 * re-init the parser, just set these two callbacks.
	 */
	memset(stats, 0, sizeof(git_indexer_stats));
	data.stats = stats;
	data.idx = idx;
	data.transport = t;
	t->parser.data = &data;
	t->transfer_finished = 0;
	memset(&settings, 0x0, sizeof(settings));
	settings.on_message_complete = on_message_complete_download_pack;
	settings.on_body = on_body_download_pack;
	*bytes = git_buf_len(oldbuf);

	if (git_indexer_stream_add(idx, git_buf_cstr(oldbuf), git_buf_len(oldbuf), stats) < 0)
		goto on_error;

	gitno_buffer_setup(transport, &buf, buffer, sizeof(buffer));

	do {
		size_t parsed;

		if ((recvd = gitno_recv(&buf)) < 0)
			goto on_error;

		parsed = http_parser_execute(&t->parser, &settings, buf.data, buf.offset);
		if (parsed != buf.offset || t->error < 0)
			goto on_error;

		*bytes += recvd;
		gitno_consume_n(&buf, parsed);
	} while (recvd > 0 && !t->transfer_finished);

	if (git_indexer_stream_finalize(idx, stats) < 0)
		goto on_error;

	git_indexer_stream_free(idx);
	return 0;

on_error:
	git_indexer_stream_free(idx);
	git_buf_free(&path);
	return -1;
}