1
0
mirror of https://github.com/git/git.git synced 2024-09-20 15:11:55 +02:00
git/hash-object.c
Dmitry Potapov 43df4f86e0 teach index_fd to work with pipes
index_fd can now work with file descriptors that are not normal files
but any readable file. If the given file descriptor is a regular file
then mmap() is used; for other files, strbuf_read is used.

The path parameter, which has been used as hint for filters, can be
NULL now to indicate that the file should be hashed literally without
any filter.

The index_pipe function is removed as redundant.

Signed-off-by: Dmitry Potapov <dpotapov@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2008-08-03 13:14:35 -07:00

135 lines
3.1 KiB
C

/*
* GIT - The information manager from hell
*
* Copyright (C) Linus Torvalds, 2005
* Copyright (C) Junio C Hamano, 2005
*/
#include "cache.h"
#include "blob.h"
#include "quote.h"
static void hash_fd(int fd, const char *type, int write_object, const char *path)
{
struct stat st;
unsigned char sha1[20];
if (fstat(fd, &st) < 0 ||
index_fd(sha1, fd, &st, write_object, type_from_string(type), path))
die(write_object
? "Unable to add %s to database"
: "Unable to hash %s", path);
printf("%s\n", sha1_to_hex(sha1));
maybe_flush_or_die(stdout, "hash to stdout");
}
static void hash_object(const char *path, const char *type, int write_object)
{
int fd;
fd = open(path, O_RDONLY);
if (fd < 0)
die("Cannot open %s", path);
hash_fd(fd, type, write_object, path);
}
static void hash_stdin_paths(const char *type, int write_objects)
{
struct strbuf buf, nbuf;
strbuf_init(&buf, 0);
strbuf_init(&nbuf, 0);
while (strbuf_getline(&buf, stdin, '\n') != EOF) {
if (buf.buf[0] == '"') {
strbuf_reset(&nbuf);
if (unquote_c_style(&nbuf, buf.buf, NULL))
die("line is badly quoted");
strbuf_swap(&buf, &nbuf);
}
hash_object(buf.buf, type, write_objects);
}
strbuf_release(&buf);
strbuf_release(&nbuf);
}
static const char hash_object_usage[] =
"git hash-object [ [-t <type>] [-w] [--stdin] <file>... | --stdin-paths < <list-of-paths> ]";
int main(int argc, char **argv)
{
int i;
const char *type = blob_type;
int write_object = 0;
const char *prefix = NULL;
int prefix_length = -1;
int no_more_flags = 0;
int hashstdin = 0;
int stdin_paths = 0;
git_config(git_default_config, NULL);
for (i = 1 ; i < argc; i++) {
if (!no_more_flags && argv[i][0] == '-') {
if (!strcmp(argv[i], "-t")) {
if (argc <= ++i)
usage(hash_object_usage);
type = argv[i];
}
else if (!strcmp(argv[i], "-w")) {
if (prefix_length < 0) {
prefix = setup_git_directory();
prefix_length =
prefix ? strlen(prefix) : 0;
}
write_object = 1;
}
else if (!strcmp(argv[i], "--")) {
no_more_flags = 1;
}
else if (!strcmp(argv[i], "--help"))
usage(hash_object_usage);
else if (!strcmp(argv[i], "--stdin-paths")) {
if (hashstdin) {
error("Can't use --stdin-paths with --stdin");
usage(hash_object_usage);
}
stdin_paths = 1;
}
else if (!strcmp(argv[i], "--stdin")) {
if (stdin_paths) {
error("Can't use %s with --stdin-paths", argv[i]);
usage(hash_object_usage);
}
if (hashstdin)
die("Multiple --stdin arguments are not supported");
hashstdin = 1;
}
else
usage(hash_object_usage);
}
else {
const char *arg = argv[i];
if (stdin_paths) {
error("Can't specify files (such as \"%s\") with --stdin-paths", arg);
usage(hash_object_usage);
}
if (hashstdin) {
hash_fd(0, type, write_object, NULL);
hashstdin = 0;
}
if (0 <= prefix_length)
arg = prefix_filename(prefix, prefix_length,
arg);
hash_object(arg, type, write_object);
no_more_flags = 1;
}
}
if (stdin_paths)
hash_stdin_paths(type, write_object);
if (hashstdin)
hash_fd(0, type, write_object, NULL);
return 0;
}