#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
#include <unistd.h>
#include <time.h>
-#include <sys/types.h>
#include <regex.h>
#include <locale.h>
static void __NORETURN die(const char *err, ...);
static void report(const char *msg, ...);
-static int read_properties(FILE *pipe, const char *separators, int (*read)(char *, int, char *, int));
+static int read_properties(FILE *pipe, const char *separators, int (*read)(char *, size_t, char *, size_t));
static void set_nonblocking_input(bool loading);
static size_t utf8_length(const char *string, size_t max_width, int *coloffset, int *trimmed);
static iconv_t opt_iconv = ICONV_NONE;
static char opt_search[SIZEOF_STR] = "";
static char opt_cdup[SIZEOF_STR] = "";
+static char opt_git_dir[SIZEOF_STR] = "";
enum option_type {
OPT_NONE,
}
static int
-read_option(char *opt, int optlen, char *value, int valuelen)
+read_option(char *opt, size_t optlen, char *value, size_t valuelen)
{
int status = OK;
} else {
/* Look for comment endings in the value. */
- int len = strcspn(value, "#");
+ size_t len = strcspn(value, "#");
if (len < valuelen) {
valuelen = len;
#define STATUS_DIFF_INDEX_CMD "git diff-index -z --cached HEAD"
#define STATUS_DIFF_FILES_CMD "git diff-files -z"
#define STATUS_LIST_OTHER_CMD \
- "_git_exclude=$(git rev-parse --git-dir)/info/exclude;" \
- "test -f \"$_git_exclude\" && exclude=\"--exclude-from=$_git_exclude\";" \
- "git ls-files -z --others --exclude-per-directory=.gitignore \"$exclude\"" \
+ "git ls-files -z --others --exclude-per-directory=.gitignore"
/* First parse staged info using git-diff-index(1), then parse unstaged
* info using git-diff-files(1), and finally untracked files using
static bool
status_open(struct view *view)
{
+ struct stat statbuf;
+ char exclude[SIZEOF_STR];
+ char cmd[SIZEOF_STR];
size_t i;
for (i = 0; i < view->lines; i++)
if (!realloc_lines(view, view->line_size + 6))
return FALSE;
+ if (!string_format(exclude, "%s/info/exclude", opt_git_dir))
+ return FALSE;
+
+ string_copy(cmd, STATUS_LIST_OTHER_CMD);
+
+ if (stat(exclude, &statbuf) >= 0) {
+ size_t cmdsize = strlen(cmd);
+
+ if (!string_format_from(cmd, &cmdsize, " %s", "--exclude-from=") ||
+ sq_quote(cmd, cmdsize, exclude) >= sizeof(cmd))
+ return FALSE;
+ }
+
if (!status_run(view, STATUS_DIFF_INDEX_CMD, TRUE, LINE_STAT_STAGED) ||
!status_run(view, STATUS_DIFF_FILES_CMD, TRUE, LINE_STAT_UNSTAGED) ||
- !status_run(view, STATUS_LIST_OTHER_CMD, FALSE, LINE_STAT_UNTRACKED))
+ !status_run(view, cmd, FALSE, LINE_STAT_UNTRACKED))
return FALSE;
return TRUE;
}
static int
-read_ref(char *id, int idlen, char *name, int namelen)
+read_ref(char *id, size_t idlen, char *name, size_t namelen)
{
struct ref *ref;
bool tag = FALSE;
}
static int
-read_repo_config_option(char *name, int namelen, char *value, int valuelen)
+read_repo_config_option(char *name, size_t namelen, char *value, size_t valuelen)
{
if (!strcmp(name, "i18n.commitencoding"))
string_ncopy(opt_encoding, value, valuelen);
}
static int
-read_repo_info(char *name, int namelen, char *value, int valuelen)
+read_repo_info(char *name, size_t namelen, char *value, size_t valuelen)
{
- if (!opt_cdup[0])
+ if (!opt_git_dir[0])
+ string_ncopy(opt_git_dir, name, namelen);
+ else
string_ncopy(opt_cdup, name, namelen);
return OK;
}
+/* XXX: The line outputted by "--show-cdup" can be empty so the option
+ * must be the last one! */
static int
load_repo_info(void)
{
- return read_properties(popen("git rev-parse --show-cdup", "r"),
+ return read_properties(popen("git rev-parse --git-dir --show-cdup 2>/dev/null", "r"),
"=", read_repo_info);
}
static int
read_properties(FILE *pipe, const char *separators,
- int (*read_property)(char *, int, char *, int))
+ int (*read_property)(char *, size_t, char *, size_t))
{
char buffer[BUFSIZ];
char *name;
string_ncopy(opt_codeset, codeset, strlen(codeset));
}
+ if (load_repo_info() == ERR)
+ die("Failed to load repo info.");
+
+ /* Require a git repository unless when running in pager mode. */
+ if (!opt_git_dir[0])
+ die("Not a git repository");
+
if (load_options() == ERR)
die("Failed to load user config.");
if (load_repo_config() == ERR)
die("Failed to load repo config.");
- if (load_repo_info() == ERR)
- die("Failed to load repo info.");
-
if (!parse_options(argc, argv))
return 0;
if (load_refs() == ERR)
die("Failed to load refs.");
- /* Require a git repository unless when running in pager mode. */
- if (refs_size == 0 && opt_request != REQ_VIEW_PAGER)
- die("Not a git repository");
-
for (i = 0; i < ARRAY_SIZE(views) && (view = &views[i]); i++)
view->cmd_env = getenv(view->cmd_env);