subsurface/git-access.c

81 lines
1.7 KiB
C
Raw Normal View History

#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <git2.h>
#include "dive.h"
/*
* If it's not a git repo, return NULL. Be very conservative.
*/
struct git_repository *is_git_repository(const char *filename, const char **branchp)
{
int flen, blen, ret;
struct stat st;
git_repository *repo;
char *loc, *branch;
flen = strlen(filename);
if (!flen || filename[--flen] != ']')
return NULL;
/* Find the matching '[' */
blen = 0;
while (flen && filename[--flen] != '[')
blen++;
if (!flen)
return NULL;
/*
* This is the "point of no return": the name matches
* the git repository name rules, and we will no longer
* return NULL.
*
* We will either return "dummy_git_repository" and the
* branch pointer will have the _whole_ filename in it,
* or we will return a real git repository with the
* branch pointer being filled in with just the branch
* name.
*
* The actual git reading/writing routines can use this
* to generate proper error messages.
*/
*branchp = filename;
loc = malloc(flen+1);
if (!loc)
return dummy_git_repository;
memcpy(loc, filename, flen);
loc[flen] = 0;
branch = malloc(blen+1);
if (!branch) {
free(loc);
return dummy_git_repository;
}
memcpy(branch, filename+flen+1, blen);
branch[blen] = 0;
if (stat(loc, &st) < 0 || !S_ISDIR(st.st_mode)) {
free(loc);
free(branch);
return dummy_git_repository;
}
ret = git_repository_open(&repo, loc);
free(loc);
if (ret < 0) {
free(branch);
return dummy_git_repository;
}
*branchp = branch;
return repo;
}