rev-parse.con commit Document "git cherry-pick" and "git revert" (de2b82c)
   1/*
   2 * rev-parse.c
   3 *
   4 * Copyright (C) Linus Torvalds, 2005
   5 */
   6#include "cache.h"
   7#include "commit.h"
   8#include "refs.h"
   9
  10#define DO_REVS         1
  11#define DO_NOREV        2
  12#define DO_FLAGS        4
  13#define DO_NONFLAGS     8
  14static int filter = ~0;
  15
  16static char *def = NULL;
  17
  18#define NORMAL 0
  19#define REVERSED 1
  20static int show_type = NORMAL;
  21static int symbolic = 0;
  22static int output_sq = 0;
  23
  24static int revs_count = 0;
  25
  26/*
  27 * Some arguments are relevant "revision" arguments,
  28 * others are about output format or other details.
  29 * This sorts it all out.
  30 */
  31static int is_rev_argument(const char *arg)
  32{
  33        static const char *rev_args[] = {
  34                "--bisect",
  35                "--header",
  36                "--max-age=",
  37                "--max-count=",
  38                "--merge-order",
  39                "--min-age=",
  40                "--no-merges",
  41                "--objects",
  42                "--parents",
  43                "--pretty",
  44                "--show-breaks",
  45                "--topo-order",
  46                "--unpacked",
  47                NULL
  48        };
  49        const char **p = rev_args;
  50
  51        for (;;) {
  52                const char *str = *p++;
  53                int len;
  54                if (!str)
  55                        return 0;
  56                len = strlen(str);
  57                if (!strcmp(arg, str) ||
  58                    (str[len-1] == '=' && !strncmp(arg, str, len)))
  59                        return 1;
  60        }
  61}
  62
  63/* Output argument as a string, either SQ or normal */
  64static void show(const char *arg)
  65{
  66        if (output_sq) {
  67                int sq = '\'', ch;
  68
  69                putchar(sq);
  70                while ((ch = *arg++)) {
  71                        if (ch == sq)
  72                                fputs("'\\'", stdout);
  73                        putchar(ch);
  74                }
  75                putchar(sq);
  76                putchar(' ');
  77        }
  78        else
  79                puts(arg);
  80}
  81
  82/* Output a revision, only if filter allows it */
  83static void show_rev(int type, const unsigned char *sha1, const char *name)
  84{
  85        if (!(filter & DO_REVS))
  86                return;
  87        def = NULL;
  88        revs_count++;
  89
  90        if (type != show_type)
  91                putchar('^');
  92        if (symbolic && name)
  93                show(name);
  94        else
  95                show(sha1_to_hex(sha1));
  96}
  97
  98/* Output a flag, only if filter allows it. */
  99static void show_flag(char *arg)
 100{
 101        if (!(filter & DO_FLAGS))
 102                return;
 103        if (filter & (is_rev_argument(arg) ? DO_REVS : DO_NOREV))
 104                show(arg);
 105}
 106
 107static void show_default(void)
 108{
 109        char *s = def;
 110
 111        if (s) {
 112                unsigned char sha1[20];
 113
 114                def = NULL;
 115                if (!get_sha1(s, sha1)) {
 116                        show_rev(NORMAL, sha1, s);
 117                        return;
 118                }
 119        }
 120}
 121
 122static int show_reference(const char *refname, const unsigned char *sha1)
 123{
 124        show_rev(NORMAL, sha1, refname);
 125        return 0;
 126}
 127
 128int main(int argc, char **argv)
 129{
 130        int i, as_is = 0, verify = 0;
 131        unsigned char sha1[20];
 132        const char *prefix = setup_git_directory();
 133        
 134        for (i = 1; i < argc; i++) {
 135                char *arg = argv[i];
 136                char *dotdot;
 137        
 138                if (as_is) {
 139                        show(arg);
 140                        continue;
 141                }
 142                if (*arg == '-') {
 143                        if (!strcmp(arg, "--")) {
 144                                as_is = 1;
 145                                continue;
 146                        }
 147                        if (!strcmp(arg, "--default")) {
 148                                def = argv[i+1];
 149                                i++;
 150                                continue;
 151                        }
 152                        if (!strcmp(arg, "--revs-only")) {
 153                                filter &= ~DO_NOREV;
 154                                continue;
 155                        }
 156                        if (!strcmp(arg, "--no-revs")) {
 157                                filter &= ~DO_REVS;
 158                                continue;
 159                        }
 160                        if (!strcmp(arg, "--flags")) {
 161                                filter &= ~DO_NONFLAGS;
 162                                continue;
 163                        }
 164                        if (!strcmp(arg, "--no-flags")) {
 165                                filter &= ~DO_FLAGS;
 166                                continue;
 167                        }
 168                        if (!strcmp(arg, "--verify")) {
 169                                filter &= ~(DO_FLAGS|DO_NOREV);
 170                                verify = 1;
 171                                continue;
 172                        }
 173                        if (!strcmp(arg, "--sq")) {
 174                                output_sq = 1;
 175                                continue;
 176                        }
 177                        if (!strcmp(arg, "--not")) {
 178                                show_type ^= REVERSED;
 179                                continue;
 180                        }
 181                        if (!strcmp(arg, "--symbolic")) {
 182                                symbolic = 1;
 183                                continue;
 184                        }
 185                        if (!strcmp(arg, "--all")) {
 186                                for_each_ref(show_reference);
 187                                continue;
 188                        }
 189                        if (!strcmp(arg, "--show-prefix")) {
 190                                if (prefix)
 191                                        puts(prefix);
 192                                continue;
 193                        }
 194                        if (verify)
 195                                die("Needed a single revision");
 196                        show_flag(arg);
 197                        continue;
 198                }
 199
 200                /* Not a flag argument */
 201                dotdot = strstr(arg, "..");
 202                if (dotdot) {
 203                        unsigned char end[20];
 204                        char *n = dotdot+2;
 205                        *dotdot = 0;
 206                        if (!get_sha1(arg, sha1)) {
 207                                if (!*n)
 208                                        n = "HEAD";
 209                                if (!get_sha1(n, end)) {
 210                                        show_rev(NORMAL, end, n);
 211                                        show_rev(REVERSED, sha1, arg);
 212                                        continue;
 213                                }
 214                        }
 215                        *dotdot = '.';
 216                }
 217                if (!get_sha1(arg, sha1)) {
 218                        show_rev(NORMAL, sha1, arg);
 219                        continue;
 220                }
 221                if (*arg == '^' && !get_sha1(arg+1, sha1)) {
 222                        show_rev(REVERSED, sha1, arg+1);
 223                        continue;
 224                }
 225                if (verify)
 226                        die("Needed a single revision");
 227                if ((filter & (DO_NONFLAGS|DO_NOREV)) ==
 228                    (DO_NONFLAGS|DO_NOREV))
 229                        show(arg);
 230        }
 231        show_default();
 232        if (verify && revs_count != 1)
 233                die("Needed a single revision");
 234        return 0;
 235}