1/*2* "git add" builtin command3*4* Copyright (C) 2006 Linus Torvalds5*/6#include <fnmatch.h>78#include "cache.h"9#include "builtin.h"10#include "dir.h"11#include "cache-tree.h"1213static const char builtin_add_usage[] =14"git-add [-n] [-v] <filepattern>...";1516static void prune_directory(struct dir_struct *dir, const char **pathspec, int prefix)17{18char *seen;19int i, specs;20struct dir_entry **src, **dst;2122for (specs = 0; pathspec[specs]; specs++)23/* nothing */;24seen = xmalloc(specs);25memset(seen, 0, specs);2627src = dst = dir->entries;28i = dir->nr;29while (--i >= 0) {30struct dir_entry *entry = *src++;31if (!match_pathspec(pathspec, entry->name, entry->len, prefix, seen)) {32free(entry);33continue;34}35*dst++ = entry;36}37dir->nr = dst - dir->entries;3839for (i = 0; i < specs; i++) {40struct stat st;41const char *match;42if (seen[i])43continue;4445/* Existing file? We must have ignored it */46match = pathspec[i];47if (!match[0] || !lstat(match, &st))48continue;49die("pathspec '%s' did not match any files", match);50}51}5253static void fill_directory(struct dir_struct *dir, const char **pathspec)54{55const char *path, *base;56int baselen;5758/* Set up the default git porcelain excludes */59memset(dir, 0, sizeof(*dir));60dir->exclude_per_dir = ".gitignore";61path = git_path("info/exclude");62if (!access(path, R_OK))63add_excludes_from_file(dir, path);6465/*66* Calculate common prefix for the pathspec, and67* use that to optimize the directory walk68*/69baselen = common_prefix(pathspec);70path = ".";71base = "";72if (baselen) {73char *common = xmalloc(baselen + 1);74common = xmalloc(baselen + 1);75memcpy(common, *pathspec, baselen);76common[baselen] = 0;77path = base = common;78}7980/* Read the directory and prune it */81read_directory(dir, path, base, baselen);82if (pathspec)83prune_directory(dir, pathspec, baselen);84}8586static int add_file_to_index(const char *path, int verbose)87{88int size, namelen;89struct stat st;90struct cache_entry *ce;9192if (lstat(path, &st))93die("%s: unable to stat (%s)", path, strerror(errno));9495if (!S_ISREG(st.st_mode) && !S_ISLNK(st.st_mode))96die("%s: can only add regular files or symbolic links", path);9798namelen = strlen(path);99size = cache_entry_size(namelen);100ce = xcalloc(1, size);101memcpy(ce->name, path, namelen);102ce->ce_flags = htons(namelen);103fill_stat_cache_info(ce, &st);104105ce->ce_mode = create_ce_mode(st.st_mode);106if (!trust_executable_bit) {107/* If there is an existing entry, pick the mode bits108* from it.109*/110int pos = cache_name_pos(path, namelen);111if (pos >= 0)112ce->ce_mode = active_cache[pos]->ce_mode;113}114115if (index_path(ce->sha1, path, &st, 1))116die("unable to index file %s", path);117if (add_cache_entry(ce, ADD_CACHE_OK_TO_ADD))118die("unable to add %s to index",path);119if (verbose)120printf("add '%s'\n", path);121cache_tree_invalidate_path(active_cache_tree, path);122return 0;123}124125static struct lock_file lock_file;126127int cmd_add(int argc, const char **argv, char **envp)128{129int i, newfd;130int verbose = 0, show_only = 0;131const char *prefix = setup_git_directory();132const char **pathspec;133struct dir_struct dir;134135git_config(git_default_config);136137newfd = hold_lock_file_for_update(&lock_file, get_index_file());138if (newfd < 0)139die("unable to create new index file");140141if (read_cache() < 0)142die("index file corrupt");143144for (i = 1; i < argc; i++) {145const char *arg = argv[i];146147if (arg[0] != '-')148break;149if (!strcmp(arg, "--")) {150i++;151break;152}153if (!strcmp(arg, "-n")) {154show_only = 1;155continue;156}157if (!strcmp(arg, "-v")) {158verbose = 1;159continue;160}161die(builtin_add_usage);162}163git_config(git_default_config);164pathspec = get_pathspec(prefix, argv + i);165166fill_directory(&dir, pathspec);167168if (show_only) {169const char *sep = "", *eof = "";170for (i = 0; i < dir.nr; i++) {171printf("%s%s", sep, dir.entries[i]->name);172sep = " ";173eof = "\n";174}175fputs(eof, stdout);176return 0;177}178179for (i = 0; i < dir.nr; i++)180add_file_to_index(dir.entries[i]->name, verbose);181182if (active_cache_changed) {183if (write_cache(newfd, active_cache, active_nr) ||184close(newfd) || commit_lock_file(&lock_file))185die("Unable to write new index file");186}187188return 0;189}