]> git.proxmox.com Git - libgit2.git/blob - src/cli/cmd_hash_object.c
New upstream version 1.5.0+ds
[libgit2.git] / src / cli / cmd_hash_object.c
1 /*
2 * Copyright (C) the libgit2 contributors. All rights reserved.
3 *
4 * This file is part of libgit2, distributed under the GNU GPL v2 with
5 * a Linking Exception. For full terms see the included COPYING file.
6 */
7
8 #include <git2.h>
9 #include "cli.h"
10 #include "cmd.h"
11
12 #include "futils.h"
13
14 #define COMMAND_NAME "hash-object"
15
16 static int show_help;
17 static char *type_name;
18 static int write_object, read_stdin, literally;
19 static char **filenames;
20
21 static const cli_opt_spec opts[] = {
22 { CLI_OPT_TYPE_SWITCH, "help", 0, &show_help, 1,
23 CLI_OPT_USAGE_HIDDEN | CLI_OPT_USAGE_STOP_PARSING, NULL,
24 "display help about the " COMMAND_NAME " command" },
25
26 { CLI_OPT_TYPE_VALUE, NULL, 't', &type_name, 0,
27 CLI_OPT_USAGE_DEFAULT, "type", "the type of object to hash (default: \"blob\")" },
28 { CLI_OPT_TYPE_SWITCH, NULL, 'w', &write_object, 1,
29 CLI_OPT_USAGE_DEFAULT, NULL, "write the object to the object database" },
30 { CLI_OPT_TYPE_SWITCH, "literally", 0, &literally, 1,
31 CLI_OPT_USAGE_DEFAULT, NULL, "do not validate the object contents" },
32 { CLI_OPT_TYPE_SWITCH, "stdin", 0, &read_stdin, 1,
33 CLI_OPT_USAGE_REQUIRED, NULL, "read content from stdin" },
34 { CLI_OPT_TYPE_ARGS, "file", 0, &filenames, 0,
35 CLI_OPT_USAGE_CHOICE, "file", "the file (or files) to read and hash" },
36 { 0 },
37 };
38
39 static void print_help(void)
40 {
41 cli_opt_usage_fprint(stdout, PROGRAM_NAME, COMMAND_NAME, opts);
42 printf("\n");
43
44 printf("Compute the object ID for a given file and optionally write that file\nto the object database.\n");
45 printf("\n");
46
47 printf("Options:\n");
48
49 cli_opt_help_fprint(stdout, opts);
50 }
51
52 static int hash_buf(git_odb *odb, git_str *buf, git_object_t type)
53 {
54 git_oid oid;
55
56 if (!literally) {
57 int valid = 0;
58
59 if (git_object_rawcontent_is_valid(&valid, buf->ptr, buf->size, type) < 0 || !valid)
60 return cli_error_git();
61 }
62
63 if (write_object) {
64 if (git_odb_write(&oid, odb, buf->ptr, buf->size, type) < 0)
65 return cli_error_git();
66 } else {
67 if (git_odb_hash(&oid, buf->ptr, buf->size, type) < 0)
68 return cli_error_git();
69 }
70
71 if (printf("%s\n", git_oid_tostr_s(&oid)) < 0)
72 return cli_error_os();
73
74 return 0;
75 }
76
77 int cmd_hash_object(int argc, char **argv)
78 {
79 git_repository *repo = NULL;
80 git_odb *odb = NULL;
81 git_str buf = GIT_STR_INIT;
82 cli_opt invalid_opt;
83 git_object_t type = GIT_OBJECT_BLOB;
84 char **filename;
85 int ret = 0;
86
87 if (cli_opt_parse(&invalid_opt, opts, argv + 1, argc - 1, CLI_OPT_PARSE_GNU))
88 return cli_opt_usage_error(COMMAND_NAME, opts, &invalid_opt);
89
90 if (show_help) {
91 print_help();
92 return 0;
93 }
94
95 if (type_name && (type = git_object_string2type(type_name)) == GIT_OBJECT_INVALID)
96 return cli_error_usage("invalid object type '%s'", type_name);
97
98 if (write_object &&
99 (git_repository_open_ext(&repo, ".", GIT_REPOSITORY_OPEN_FROM_ENV, NULL) < 0 ||
100 git_repository_odb(&odb, repo) < 0)) {
101 ret = cli_error_git();
102 goto done;
103 }
104
105 /*
106 * TODO: we're reading blobs, we shouldn't pull them all into main
107 * memory, we should just stream them into the odb instead.
108 * (Or create a `git_odb_writefile` API.)
109 */
110 if (read_stdin) {
111 if (git_futils_readbuffer_fd_full(&buf, fileno(stdin)) < 0) {
112 ret = cli_error_git();
113 goto done;
114 }
115
116 if ((ret = hash_buf(odb, &buf, type)) != 0)
117 goto done;
118 } else {
119 for (filename = filenames; *filename; filename++) {
120 if (git_futils_readbuffer(&buf, *filename) < 0) {
121 ret = cli_error_git();
122 goto done;
123 }
124
125 if ((ret = hash_buf(odb, &buf, type)) != 0)
126 goto done;
127 }
128 }
129
130 done:
131 git_str_dispose(&buf);
132 git_odb_free(odb);
133 git_repository_free(repo);
134 return ret;
135 }