hash-object.con commit sha1_file.c: resolve confusion EACCES vs EPERM (3524357)
   1/*
   2 * GIT - The information manager from hell
   3 *
   4 * Copyright (C) Linus Torvalds, 2005
   5 * Copyright (C) Junio C Hamano, 2005
   6 */
   7#include "cache.h"
   8#include "blob.h"
   9#include "quote.h"
  10
  11static void hash_object(const char *path, enum object_type type, int write_object)
  12{
  13        int fd;
  14        struct stat st;
  15        unsigned char sha1[20];
  16        fd = open(path, O_RDONLY);
  17        if (fd < 0 ||
  18            fstat(fd, &st) < 0 ||
  19            index_fd(sha1, fd, &st, write_object, type, path))
  20                die(write_object
  21                    ? "Unable to add %s to database"
  22                    : "Unable to hash %s", path);
  23        printf("%s\n", sha1_to_hex(sha1));
  24        maybe_flush_or_die(stdout, "hash to stdout");
  25}
  26
  27static void hash_stdin(const char *type, int write_object)
  28{
  29        unsigned char sha1[20];
  30        if (index_pipe(sha1, 0, type, write_object))
  31                die("Unable to add stdin to database");
  32        printf("%s\n", sha1_to_hex(sha1));
  33}
  34
  35static void hash_stdin_paths(const char *type, int write_objects)
  36{
  37        struct strbuf buf, nbuf;
  38
  39        strbuf_init(&buf, 0);
  40        strbuf_init(&nbuf, 0);
  41        while (strbuf_getline(&buf, stdin, '\n') != EOF) {
  42                if (buf.buf[0] == '"') {
  43                        strbuf_reset(&nbuf);
  44                        if (unquote_c_style(&nbuf, buf.buf, NULL))
  45                                die("line is badly quoted");
  46                        strbuf_swap(&buf, &nbuf);
  47                }
  48                hash_object(buf.buf, type_from_string(type), write_objects);
  49        }
  50        strbuf_release(&buf);
  51        strbuf_release(&nbuf);
  52}
  53
  54static const char hash_object_usage[] =
  55"git hash-object [ [-t <type>] [-w] [--stdin] <file>... | --stdin-paths < <list-of-paths> ]";
  56
  57int main(int argc, char **argv)
  58{
  59        int i;
  60        const char *type = blob_type;
  61        int write_object = 0;
  62        const char *prefix = NULL;
  63        int prefix_length = -1;
  64        int no_more_flags = 0;
  65        int hashstdin = 0;
  66        int stdin_paths = 0;
  67
  68        git_config(git_default_config, NULL);
  69
  70        for (i = 1 ; i < argc; i++) {
  71                if (!no_more_flags && argv[i][0] == '-') {
  72                        if (!strcmp(argv[i], "-t")) {
  73                                if (argc <= ++i)
  74                                        usage(hash_object_usage);
  75                                type = argv[i];
  76                        }
  77                        else if (!strcmp(argv[i], "-w")) {
  78                                if (prefix_length < 0) {
  79                                        prefix = setup_git_directory();
  80                                        prefix_length =
  81                                                prefix ? strlen(prefix) : 0;
  82                                }
  83                                write_object = 1;
  84                        }
  85                        else if (!strcmp(argv[i], "--")) {
  86                                no_more_flags = 1;
  87                        }
  88                        else if (!strcmp(argv[i], "--help"))
  89                                usage(hash_object_usage);
  90                        else if (!strcmp(argv[i], "--stdin-paths")) {
  91                                if (hashstdin) {
  92                                        error("Can't use --stdin-paths with --stdin");
  93                                        usage(hash_object_usage);
  94                                }
  95                                stdin_paths = 1;
  96
  97                        }
  98                        else if (!strcmp(argv[i], "--stdin")) {
  99                                if (stdin_paths) {
 100                                        error("Can't use %s with --stdin-paths", argv[i]);
 101                                        usage(hash_object_usage);
 102                                }
 103                                if (hashstdin)
 104                                        die("Multiple --stdin arguments are not supported");
 105                                hashstdin = 1;
 106                        }
 107                        else
 108                                usage(hash_object_usage);
 109                }
 110                else {
 111                        const char *arg = argv[i];
 112
 113                        if (stdin_paths) {
 114                                error("Can't specify files (such as \"%s\") with --stdin-paths", arg);
 115                                usage(hash_object_usage);
 116                        }
 117
 118                        if (hashstdin) {
 119                                hash_stdin(type, write_object);
 120                                hashstdin = 0;
 121                        }
 122                        if (0 <= prefix_length)
 123                                arg = prefix_filename(prefix, prefix_length,
 124                                                      arg);
 125                        hash_object(arg, type_from_string(type), write_object);
 126                        no_more_flags = 1;
 127                }
 128        }
 129
 130        if (stdin_paths)
 131                hash_stdin_paths(type, write_object);
 132
 133        if (hashstdin)
 134                hash_stdin(type, write_object);
 135        return 0;
 136}