Skip to content

Commit

Permalink
Merge branch 'dp/hash-literally'
Browse files Browse the repository at this point in the history
* dp/hash-literally:
  add --no-filters option to git hash-object
  add --path option to git hash-object
  use parse_options() in git hash-object
  correct usage help string for git-hash-object
  correct argument checking test for git hash-object
  teach index_fd to work with pipes
  • Loading branch information
Junio C Hamano committed Aug 20, 2008
2 parents 614eef2 + 4a3d85d commit d8eec50
Show file tree
Hide file tree
Showing 5 changed files with 178 additions and 122 deletions.
20 changes: 19 additions & 1 deletion Documentation/git-hash-object.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ git-hash-object - Compute object ID and optionally creates a blob from a file

SYNOPSIS
--------
'git hash-object' [-t <type>] [-w] [--stdin | --stdin-paths] [--] <file>...
[verse]
'git hash-object' [-t <type>] [-w] [--path=<file>|--no-filters] [--stdin] [--] <file>...
'git hash-object' [-t <type>] [-w] --stdin-paths < <list-of-paths>

DESCRIPTION
-----------
Expand All @@ -35,6 +37,22 @@ OPTIONS
--stdin-paths::
Read file names from stdin instead of from the command-line.

--path::
Hash object as it were located at the given path. The location of
file does not directly influence on the hash value, but path is
used to determine what git filters should be applied to the object
before it can be placed to the object database, and, as result of
applying filters, the actual blob put into the object database may
differ from the given file. This option is mainly useful for hashing
temporary files located outside of the working directory or files
read from stdin.

--no-filters::
Hash the contents as is, ignoring any input filter that would
have been chosen by the attributes mechanism, including crlf
conversion. If the file is read from standard input then this
is always implied, unless the --path option is given.

Author
------
Written by Junio C Hamano <gitster@pobox.com>
Expand Down
1 change: 0 additions & 1 deletion cache.h
Original file line number Diff line number Diff line change
Expand Up @@ -391,7 +391,6 @@ extern int ie_modified(const struct index_state *, struct cache_entry *, struct

extern int ce_path_match(const struct cache_entry *ce, const char **pathspec);
extern int index_fd(unsigned char *sha1, int fd, struct stat *st, int write_object, enum object_type type, const char *path);
extern int index_pipe(unsigned char *sha1, int fd, const char *type, int write_object);
extern int index_path(unsigned char *sha1, const char *path, struct stat *st, int write_object);
extern void fill_stat_cache_info(struct cache_entry *ce, struct stat *st);

Expand Down
159 changes: 79 additions & 80 deletions hash-object.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,29 +7,29 @@
#include "cache.h"
#include "blob.h"
#include "quote.h"
#include "parse-options.h"

static void hash_object(const char *path, enum object_type type, int write_object)
static void hash_fd(int fd, const char *type, int write_object, const char *path)
{
int fd;
struct stat st;
unsigned char sha1[20];
fd = open(path, O_RDONLY);
if (fd < 0 ||
fstat(fd, &st) < 0 ||
index_fd(sha1, fd, &st, write_object, type, path))
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_stdin(const char *type, int write_object)
static void hash_object(const char *path, const char *type, int write_object,
const char *vpath)
{
unsigned char sha1[20];
if (index_pipe(sha1, 0, type, write_object))
die("Unable to add stdin to database");
printf("%s\n", sha1_to_hex(sha1));
int fd;
fd = open(path, O_RDONLY);
if (fd < 0)
die("Cannot open %s", path);
hash_fd(fd, type, write_object, vpath);
}

static void hash_stdin_paths(const char *type, int write_objects)
Expand All @@ -45,92 +45,91 @@ static void hash_stdin_paths(const char *type, int write_objects)
die("line is badly quoted");
strbuf_swap(&buf, &nbuf);
}
hash_object(buf.buf, type_from_string(type), write_objects);
hash_object(buf.buf, type, write_objects, buf.buf);
}
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> ]";
static const char * const hash_object_usage[] = {
"git hash-object [-t <type>] [-w] [--path=<file>|--no-filters] [--stdin] [--] <file>...",
"git hash-object --stdin-paths < <list-of-paths>",
NULL
};

int main(int argc, char **argv)
static const char *type;
static int write_object;
static int hashstdin;
static int stdin_paths;
static int no_filters;
static const char *vpath;

static const struct option hash_object_options[] = {
OPT_STRING('t', NULL, &type, "type", "object type"),
OPT_BOOLEAN('w', NULL, &write_object, "write the object into the object database"),
OPT_BOOLEAN( 0 , "stdin", &hashstdin, "read the object from stdin"),
OPT_BOOLEAN( 0 , "stdin-paths", &stdin_paths, "read file names from stdin"),
OPT_BOOLEAN( 0 , "no-filters", &no_filters, "store file as is without filters"),
OPT_STRING( 0 , "path", &vpath, "file", "process file as it were from this path"),
OPT_END()
};

int main(int argc, const 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;
const char *errstr = NULL;

type = blob_type;

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_stdin(type, write_object);
hashstdin = 0;
}
if (0 <= prefix_length)
arg = prefix_filename(prefix, prefix_length,
arg);
hash_object(arg, type_from_string(type), write_object);
no_more_flags = 1;
}
argc = parse_options(argc, argv, hash_object_options, hash_object_usage, 0);

if (write_object) {
prefix = setup_git_directory();
prefix_length = prefix ? strlen(prefix) : 0;
if (vpath && prefix)
vpath = prefix_filename(prefix, prefix_length, vpath);
}

if (stdin_paths) {
if (hashstdin)
errstr = "Can't use --stdin-paths with --stdin";
else if (argc)
errstr = "Can't specify files with --stdin-paths";
else if (vpath)
errstr = "Can't use --stdin-paths with --path";
else if (no_filters)
errstr = "Can't use --stdin-paths with --no-filters";
}
else {
if (hashstdin > 1)
errstr = "Multiple --stdin arguments are not supported";
if (vpath && no_filters)
errstr = "Can't use --path with --no-filters";
}

if (errstr) {
error (errstr);
usage_with_options(hash_object_usage, hash_object_options);
}

if (hashstdin)
hash_fd(0, type, write_object, vpath);

for (i = 0 ; i < argc; i++) {
const char *arg = argv[i];

if (0 <= prefix_length)
arg = prefix_filename(prefix, prefix_length, arg);
hash_object(arg, type, write_object,
no_filters ? NULL : vpath ? vpath : arg);
}

if (stdin_paths)
hash_stdin_paths(type, write_object);

if (hashstdin)
hash_stdin(type, write_object);
return 0;
}
64 changes: 28 additions & 36 deletions sha1_file.c
Original file line number Diff line number Diff line change
Expand Up @@ -2360,51 +2360,22 @@ int has_sha1_file(const unsigned char *sha1)
return has_loose_object(sha1);
}

int index_pipe(unsigned char *sha1, int fd, const char *type, int write_object)
static int index_mem(unsigned char *sha1, void *buf, size_t size,
int write_object, enum object_type type, const char *path)
{
struct strbuf buf;
int ret;

strbuf_init(&buf, 0);
if (strbuf_read(&buf, fd, 4096) < 0) {
strbuf_release(&buf);
return -1;
}

if (!type)
type = blob_type;
if (write_object)
ret = write_sha1_file(buf.buf, buf.len, type, sha1);
else
ret = hash_sha1_file(buf.buf, buf.len, type, sha1);
strbuf_release(&buf);

return ret;
}

int index_fd(unsigned char *sha1, int fd, struct stat *st, int write_object,
enum object_type type, const char *path)
{
size_t size = xsize_t(st->st_size);
void *buf = NULL;
int ret, re_allocated = 0;

if (size)
buf = xmmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0);
close(fd);

if (!type)
type = OBJ_BLOB;

/*
* Convert blobs to git internal format
*/
if ((type == OBJ_BLOB) && S_ISREG(st->st_mode)) {
if ((type == OBJ_BLOB) && path) {
struct strbuf nbuf;
strbuf_init(&nbuf, 0);
if (convert_to_git(path, buf, size, &nbuf,
write_object ? safe_crlf : 0)) {
munmap(buf, size);
buf = strbuf_detach(&nbuf, &size);
re_allocated = 1;
}
Expand All @@ -2414,12 +2385,33 @@ int index_fd(unsigned char *sha1, int fd, struct stat *st, int write_object,
ret = write_sha1_file(buf, size, typename(type), sha1);
else
ret = hash_sha1_file(buf, size, typename(type), sha1);
if (re_allocated) {
if (re_allocated)
free(buf);
return ret;
}
if (size)
return ret;
}

int index_fd(unsigned char *sha1, int fd, struct stat *st, int write_object,
enum object_type type, const char *path)
{
int ret;
size_t size = xsize_t(st->st_size);

if (!S_ISREG(st->st_mode)) {
struct strbuf sbuf;
strbuf_init(&sbuf, 0);
if (strbuf_read(&sbuf, fd, 4096) >= 0)
ret = index_mem(sha1, sbuf.buf, sbuf.len, write_object,
type, path);
else
ret = -1;
strbuf_release(&sbuf);
} else if (size) {
void *buf = xmmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0);
ret = index_mem(sha1, buf, size, write_object, type, path);
munmap(buf, size);
} else
ret = index_mem(sha1, NULL, size, write_object, type, path);
close(fd);
return ret;
}

Expand Down
Loading

0 comments on commit d8eec50

Please sign in to comment.