mirror of
https://github.com/radareorg/radare2.git
synced 2025-02-18 21:28:15 +00:00
Initial refactoring of the version control api ##rvc
This commit is contained in:
parent
b680675d16
commit
b2ff7de0f0
@ -42,7 +42,7 @@ R_API void r_project_close(RProject *p) {
|
||||
R_FREE (p->name);
|
||||
R_FREE (p->path);
|
||||
if (p->rvc) {
|
||||
r_vc_close (p->rvc, true);
|
||||
rvc_close (p->rvc, true);
|
||||
p->rvc = NULL;
|
||||
}
|
||||
}
|
||||
|
@ -320,7 +320,7 @@ static bool r_core_project_load(RCore *core, const char *prj_name, const char *r
|
||||
char *prj_path = r_file_dirname(rcpath);
|
||||
if (prj_path) {
|
||||
//check if the project uses git
|
||||
Rvc *vc = rvc_git_open (prj_path);
|
||||
Rvc *vc = rvc_open (prj_path, RVC_TYPE_GIT);
|
||||
core->prj->rvc = vc;
|
||||
free (prj_path);
|
||||
} else {
|
||||
@ -687,7 +687,7 @@ R_API bool r_core_project_save(RCore *core, const char *prj_name) {
|
||||
if (core->prj->rvc || r_config_get_b (core->config, "prj.vc")) {
|
||||
// assume that if the repo is not loaded, the repo doesn't exist
|
||||
if (!core->prj->rvc) {
|
||||
core->prj->rvc = rvc_init (prj_dir, RVC_TYPE_GIT);
|
||||
core->prj->rvc = rvc_open (prj_dir, RVC_TYPE_GIT);
|
||||
if (!core->prj->rvc) {
|
||||
R_LOG_WARN ("Cannot initialize git repositorty");
|
||||
free (prj_dir);
|
||||
@ -700,13 +700,13 @@ R_API bool r_core_project_save(RCore *core, const char *prj_name) {
|
||||
if (r_list_append (paths, prj_dir)) {
|
||||
const char *author = r_config_get (core->config, "cfg.user");
|
||||
const char *message = r_config_get (core->config, "prj.vc.message");
|
||||
if (!rvc_git_commit (core->prj->rvc, message, author, paths)) {
|
||||
if (!rvc_commit (core->prj->rvc, message, author, paths)) {
|
||||
r_list_free (paths);
|
||||
free (prj_dir);
|
||||
free (script_path);
|
||||
return false;
|
||||
}
|
||||
r_vc_save (core->prj->rvc);
|
||||
rvc_save (core->prj->rvc);
|
||||
} else {
|
||||
r_list_free (paths);
|
||||
free (prj_dir);
|
||||
|
@ -1616,7 +1616,7 @@ R_API void r_anal_class_list_vtables(RAnal *anal, const char *class_name);
|
||||
R_API void r_anal_class_list_vtable_offset_functions(RAnal *anal, const char *class_name, ut64 offset);
|
||||
R_API RGraph/*<RGraphNodeInfo>*/ *r_anal_class_get_inheritance_graph(RAnal *anal);
|
||||
|
||||
R_IPI RAnalEsilCFG *r_anal_esil_cfg_new(void);
|
||||
R_API RAnalEsilCFG *r_anal_esil_cfg_new(void);
|
||||
R_API RAnalEsilCFG *r_anal_esil_cfg_expr(RAnalEsilCFG *cfg, RAnal *anal, const ut64 off, char *expr);
|
||||
R_API RAnalEsilCFG *r_anal_esil_cfg_op(RAnalEsilCFG *cfg, RAnal *anal, RAnalOp *op);
|
||||
R_API void r_anal_esil_cfg_merge_blocks(RAnalEsilCFG *cfg);
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* radare - LGPL - Copyright 2021 - RHL120, pancake */
|
||||
/* radare - LGPL - Copyright 2021-2022 - RHL120, pancake */
|
||||
|
||||
#ifndef R_RVC_H
|
||||
#define R_RVC_H 1
|
||||
@ -8,7 +8,7 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <r_core.h>
|
||||
#include <r_util.h>
|
||||
#include <sdb.h>
|
||||
|
||||
typedef struct r_vc_blob_t {
|
||||
@ -29,61 +29,60 @@ typedef struct r_vc_t {
|
||||
const struct rvc_plugin_t *p;
|
||||
} Rvc;
|
||||
|
||||
typedef bool (*RvcPluginBranch)(struct r_vc_t *rvc, const char *bname);
|
||||
typedef bool (*RvcPluginCommit)(struct r_vc_t *rvc, const char *message, const char *author, const RList *files);
|
||||
typedef bool (*RvcPluginCheckout)(struct r_vc_t *rvc, const char *bname);
|
||||
typedef RList *(*RvcPluginBranches)(struct r_vc_t *rvc);
|
||||
typedef void (*RvcPluginClose)(struct r_vc_t *vc, bool save);
|
||||
typedef char *(*RvcPluginCurrentBranch)(struct r_vc_t *rvc);
|
||||
typedef bool (*RvcPluginPrintCommits) (struct r_vc_t *rvc);
|
||||
typedef RList *(*RvcPluginUncommited) (struct r_vc_t *rvc);
|
||||
typedef bool (*RvcPluginReset)(struct r_vc_t *rvc);
|
||||
typedef bool (*RvcPluginClone)(const struct r_vc_t *rvc, const char *dst);
|
||||
typedef bool (*RvcPluginSave)(struct r_vc_t *vc);
|
||||
typedef Rvc *(*RvcPluginOpen)(const char *path);
|
||||
|
||||
typedef struct rvc_plugin_t {
|
||||
const char *name;
|
||||
const char *author;
|
||||
const char *desc;
|
||||
const char *license;
|
||||
const char *const name;
|
||||
const char *const author;
|
||||
const char *const desc;
|
||||
const char *const license;
|
||||
RvcType type;
|
||||
bool (*commit)(struct r_vc_t *rvc, const char *message, const char *author, const RList *files);
|
||||
bool (*branch)(struct r_vc_t *rvc, const char *bname);
|
||||
bool (*checkout)(struct r_vc_t *rvc, const char *bname);
|
||||
RList *(*get_branches) (struct r_vc_t *rvc);
|
||||
RList *(*get_uncommitted) (struct r_vc_t *rvc);
|
||||
bool (*print_commits) (struct r_vc_t *rvc);
|
||||
char *(*current_branch)(struct r_vc_t *rvc);
|
||||
bool (*reset)(struct r_vc_t *rvc);
|
||||
bool (*clone)(const struct r_vc_t *rvc, const char *dst);
|
||||
void (*close)(struct r_vc_t *vc, bool save);
|
||||
bool (*save)(struct r_vc_t *vc);
|
||||
RvcPluginCommit commit;
|
||||
RvcPluginCheckout checkout;
|
||||
RvcPluginBranch branch;
|
||||
RvcPluginBranches branches;
|
||||
RvcPluginCurrentBranch curbranch;
|
||||
RvcPluginUncommited uncommited;
|
||||
RvcPluginPrintCommits log;
|
||||
RvcPluginReset reset;
|
||||
RvcPluginClone clone;
|
||||
RvcPluginClose close;
|
||||
RvcPluginSave save;
|
||||
RvcPluginOpen open;
|
||||
} RvcPlugin;
|
||||
|
||||
R_API Rvc *rvc_init(const char *path, RvcType type);
|
||||
R_API Rvc *rvc_open(const char *rp, RvcType type);
|
||||
R_API void rvc_close(Rvc *vc, bool save);
|
||||
R_API bool rvc_save(Rvc *vc);
|
||||
R_API void rvc_free(Rvc *vc);
|
||||
|
||||
R_API Rvc *r_vc_git_init(const char *path);
|
||||
R_API bool r_vc_git_branch(Rvc *vc, const char *name);
|
||||
R_API bool r_vc_git_checkout(Rvc *vc, const char *name);
|
||||
R_API bool r_vc_git_add(Rvc *vc, const RList *files);
|
||||
R_API bool r_vc_git_commit(Rvc *rvc, const char *message, const char *author, const RList *files);
|
||||
R_API Rvc *r_vc_git_open(const char *path);
|
||||
R_API RList *rvc_branches(Rvc *vc);
|
||||
|
||||
R_API bool r_vc_commit(Rvc *rvc, const char *message, const char *author, const RList *files);
|
||||
R_API bool r_vc_branch(Rvc *rvc, const char *bname);
|
||||
R_API bool rvc_commit(Rvc *rvc, const char *message, const char *author, const RList *files);
|
||||
R_API bool rvc_branch(Rvc *rvc, const char *bname);
|
||||
R_API Rvc *r_vc_new(const char *path);
|
||||
R_API bool r_vc_checkout(Rvc *rvc, const char *bname);
|
||||
R_API RList *r_vc_get_branches(Rvc *rvc);
|
||||
R_API RList *r_vc_get_uncommitted(Rvc *rvc);
|
||||
R_API bool r_vc_log(Rvc *rvc);
|
||||
R_API char *r_vc_current_branch(Rvc *rvc);
|
||||
R_API bool r_vc_reset(Rvc *rvc);
|
||||
R_API bool r_vc_clone(const Rvc *rvc, const char *dst);
|
||||
R_API Rvc *r_vc_open(const char *rp, RvcType type);
|
||||
R_API void r_vc_close(Rvc *vc, bool save);
|
||||
R_API bool r_vc_save(Rvc *vc);
|
||||
R_API void r_vc_free(Rvc *vc);
|
||||
|
||||
R_API RList *r_vc_git_get_branches(Rvc *rvc);
|
||||
R_API RList *r_vc_git_get_uncommitted(Rvc *rvc);
|
||||
R_API bool r_vc_git_log(Rvc *rvc);
|
||||
R_API char *r_vc_git_current_branch(Rvc *rvc);
|
||||
R_API bool r_vc_git_reset(Rvc *rvc);
|
||||
R_API bool r_vc_git_clone(const Rvc *rvc, const char *dst);
|
||||
R_API void r_vc_git_close(Rvc *vc, bool save);
|
||||
R_API bool rvc_git_checkout(Rvc *rvc, const char *bname);
|
||||
|
||||
R_API Rvc *rvc_git_init(const char *path);
|
||||
R_API Rvc *rvc_git_open(const char *path);
|
||||
R_API bool r_vc_use(Rvc *vc, RvcType);
|
||||
R_API bool rvc_use(Rvc *vc, RvcType);
|
||||
R_API bool rvc_checkout(Rvc *vc, const char *bname);
|
||||
R_API bool rvc_git_commit(Rvc *rvc, const char *message, const char *author, const RList *files);
|
||||
R_API void rvc_git_close(struct r_vc_t *vc, bool save);
|
||||
R_API RList *rvc_git_get_branches(Rvc *rvc);
|
||||
|
@ -22,7 +22,7 @@ static void help(void) {
|
||||
" commit [message] [files...] commit the files with the message\n"
|
||||
" checkout [branch] set the current branch to the given branch\n"
|
||||
" status print a status message\n"
|
||||
" reset remove all uncommitted changes\n"
|
||||
" reset remove all uncommited changes\n"
|
||||
" log print all commits\n"
|
||||
" RAVC2_USER=[n] override cfg.user value to author commit\n"
|
||||
);
|
||||
@ -95,16 +95,16 @@ R_API int r_main_ravc2(int argc, const char **argv) {
|
||||
if (opt.argc <= 2) {
|
||||
R_LOG_ERROR ("Usage: ravc2 <git | rvc>");
|
||||
} else if (!strcmp (opt.argv[opt.ind + 1], "git")) {
|
||||
rvc = r_vc_git_init (rp);
|
||||
rvc = rvc_open (rp, RVC_TYPE_GIT);
|
||||
} else if (!strcmp (opt.argv[opt.ind + 1], "rvc")) {
|
||||
rvc = r_vc_new (rp);
|
||||
rvc = rvc_open (rp, RVC_TYPE_RVC);
|
||||
} else {
|
||||
R_LOG_ERROR ("unknown option %s", opt.argv[opt.ind + 1]);
|
||||
}
|
||||
free (rp);
|
||||
return rvc? !r_vc_save (rvc) : 1;
|
||||
return rvc? !rvc_save (rvc) : 1;
|
||||
}
|
||||
Rvc *rvc = rvc_git_open (rp);
|
||||
Rvc *rvc = rvc_open (rp, RVC_TYPE_ANY);
|
||||
if (!rvc) {
|
||||
R_LOG_ERROR ("Invalid action or repository in %s", rp);
|
||||
R_FREE (rp);
|
||||
@ -115,13 +115,13 @@ R_API int r_main_ravc2(int argc, const char **argv) {
|
||||
// commands that need Rvc *
|
||||
if (!strcmp (action, "branch")) {
|
||||
if (opt.argc <= 2) {
|
||||
RList *branches = rvc_git_get_branches (rvc);
|
||||
RList *branches = rvc_branches (rvc);
|
||||
RListIter *iter;
|
||||
char *branch;
|
||||
r_list_foreach (branches, iter, branch) {
|
||||
printf ("%s\n", branch);
|
||||
}
|
||||
r_list_free(branches);
|
||||
r_list_free (branches);
|
||||
} else {
|
||||
// TODO: use api not plugin fields: rvc_branch (rvc, opt.argv[opt.ind + 1]);
|
||||
save = rvc->p->branch (rvc, opt.argv[opt.ind + 1]);
|
||||
@ -155,32 +155,33 @@ R_API int r_main_ravc2(int argc, const char **argv) {
|
||||
free (message);
|
||||
}
|
||||
} else if (!strcmp (action, "checkout") && opt.argc > 2) {
|
||||
save = rvc_git_checkout (rvc, opt.argv[opt.ind + 1]);
|
||||
save = rvc_checkout (rvc, opt.argv[opt.ind + 1]);
|
||||
} else if (!strcmp (action, "status")) {
|
||||
char *current_branch = rvc->p->current_branch (rvc);
|
||||
char *current_branch = rvc->p->curbranch (rvc);
|
||||
if (current_branch) {
|
||||
printf ("Branch: %s\n", current_branch);
|
||||
RList *uncommitted = rvc->p->get_uncommitted (rvc);
|
||||
if (r_list_empty (uncommitted)) {
|
||||
RList *uncommited = rvc->p->uncommited (rvc);
|
||||
if (r_list_empty (uncommited)) {
|
||||
printf ("All files are committed\n");
|
||||
} else {
|
||||
printf ("The following files were NOT committed:\n");
|
||||
RListIter *iter;
|
||||
const char *file;
|
||||
r_list_foreach (uncommitted, iter, file) {
|
||||
r_list_foreach (uncommited, iter, file) {
|
||||
printf ("%s\n", file);
|
||||
}
|
||||
}
|
||||
r_list_free (uncommitted);
|
||||
r_list_free (uncommited);
|
||||
}
|
||||
} else if (!strcmp (action, "reset")) {
|
||||
save = rvc->p->reset (rvc);
|
||||
} else if (!strcmp (action, "log")) {
|
||||
save = rvc->p->print_commits (rvc);
|
||||
save = rvc->p->log (rvc);
|
||||
} else {
|
||||
R_LOG_ERROR ("Incorrect command");
|
||||
}
|
||||
ret:
|
||||
rvc_git_close (rvc, save);
|
||||
rvc_close (rvc, save);
|
||||
// rvc_git_close (rvc, save);
|
||||
return !save;
|
||||
}
|
||||
|
@ -5,7 +5,7 @@ CFLAGS+=-DR2_PLUGIN_INCORE -I$(TOP)/shlr
|
||||
PCLIBS=@LIBZIP@ @DL_LIBS@
|
||||
OBJS=mem.o unum.o str.o hex.o file.o range.o charset.o xdg.o rxml.o
|
||||
OBJS+=prof.o cache.o sys.o buf.o sys_w32.o ubase64.o base85.o base91.o
|
||||
OBJS+=list.o chmod.o graph.o event.o alloc.o donut.o print_code.o rvc.o
|
||||
OBJS+=list.o chmod.o graph.o event.o alloc.o donut.o print_code.o
|
||||
OBJS+=regex/regcomp.o regex/regerror.o regex/regexec.o uleb128.o rstr.o
|
||||
OBJS+=sandbox.o calc.o thread.o thread_sem.o thread_lock.o thread_cond.o thread_chan.o
|
||||
OBJS+=strpool.o bitmap.o time.o format.o pie.o print.o utype.o w32.o w32dw.o
|
||||
@ -15,6 +15,7 @@ OBJS+=udiff.o bdiff.o stack.o queue.o tree.o idpool.o assert.o bplist.o
|
||||
OBJS+=punycode.o pkcs7.o x509.o asn1.o asn1_str.o json_parser.o json_indent.o skiplist.o
|
||||
OBJS+=pj.o rbtree.o intervaltree.o qrcode.o vector.o skyline.o str_constpool.o str_trim.o
|
||||
OBJS+=ascii_table.o protobuf.o graph_drawable.o axml.o sstext.o new_rbtree.o token.o
|
||||
OBJS+=rvc.o rvc_git.o rvc_rvc.o
|
||||
|
||||
ifeq (${HAVE_GPERF},1)
|
||||
OBJS+=d/ascii.o
|
||||
|
@ -8,6 +8,8 @@ r_util_sources = [
|
||||
'alloc.c',
|
||||
'rxml.c',
|
||||
'rvc.c',
|
||||
'rvc_git.c',
|
||||
'rvc_rvc.c',
|
||||
'charset.c',
|
||||
'donut.c',
|
||||
'token.c',
|
||||
|
1625
libr/util/rvc.c
1625
libr/util/rvc.c
File diff suppressed because it is too large
Load Diff
305
libr/util/rvc_git.c
Normal file
305
libr/util/rvc_git.c
Normal file
@ -0,0 +1,305 @@
|
||||
/* radare - LGPL - Copyright 2021-2022 - RHL120, pancake */
|
||||
// GIT commands as APIs
|
||||
#define R_LOG_ORIGIN "vc.git"
|
||||
#include <rvc.h>
|
||||
|
||||
|
||||
static Rvc *open_git(const char *path) {
|
||||
char *git_path = r_file_new (path, ".git", NULL);
|
||||
if (!git_path || !r_file_is_directory (git_path)) {
|
||||
char *escpath = r_str_escape (path);
|
||||
int ret = r_sys_cmdf ("git init \"%s\"", escpath);
|
||||
free (escpath);
|
||||
if (ret != 0) {
|
||||
R_LOG_WARN ("git init failed");
|
||||
}
|
||||
if (!r_file_is_directory (git_path)) {
|
||||
free (git_path);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
free (git_path);
|
||||
Rvc *vc = R_NEW (Rvc);
|
||||
if (!vc) {
|
||||
return NULL;
|
||||
}
|
||||
vc->path = r_str_new (path);
|
||||
if (!vc->path) {
|
||||
free (vc);
|
||||
return NULL;
|
||||
}
|
||||
vc->db = NULL;
|
||||
if (!rvc_use (vc, RVC_TYPE_GIT)) {
|
||||
rvc_free (vc);
|
||||
return NULL;
|
||||
}
|
||||
return vc;
|
||||
}
|
||||
|
||||
static bool _git_branch(Rvc *vc, const char *name) {
|
||||
char *escpath = r_str_escape (vc->path);
|
||||
if (!escpath) {
|
||||
return false;
|
||||
}
|
||||
char *escname = r_str_escape (name);
|
||||
if (!escname) {
|
||||
free (escpath);
|
||||
return false;
|
||||
}
|
||||
int ret = r_sys_cmdf ("git -C \"%s\" branch \"%s\"", escpath, escname);
|
||||
free (escpath);
|
||||
free (escname);
|
||||
return !ret;
|
||||
}
|
||||
|
||||
static bool checkout_git(Rvc *vc, const char *name) {
|
||||
char *escpath = r_str_escape (vc->path);
|
||||
char *escname = r_str_escape (name);
|
||||
int ret = r_sys_cmdf ("git -C \"%s\" checkout \"%s\"", escpath, escname);
|
||||
free (escname);
|
||||
free (escpath);
|
||||
return !ret;
|
||||
}
|
||||
|
||||
static bool add_git(Rvc *vc, const RList *files) {
|
||||
RListIter *iter;
|
||||
const char *fname;
|
||||
char *cwd = r_sys_getdir ();
|
||||
if (!cwd) {
|
||||
return false;
|
||||
}
|
||||
if (!r_sys_chdir (vc->path)) {
|
||||
free (cwd);
|
||||
return false;
|
||||
}
|
||||
bool ret = true;
|
||||
r_list_foreach (files, iter, fname) {
|
||||
char *escfname = r_str_escape (fname);
|
||||
if (!escfname) {
|
||||
ret = false;
|
||||
break;
|
||||
}
|
||||
ret &= !r_sys_cmdf ("git add \"%s\"", escfname);
|
||||
free (escfname);
|
||||
}
|
||||
if (!r_sys_chdir (cwd)) {
|
||||
free (cwd);
|
||||
return false;
|
||||
}
|
||||
free (cwd);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static bool commit_git(Rvc *vc, const char *_message, const char *author, const RList *files) {
|
||||
char *message = _message? strdup (_message): NULL;
|
||||
if (!add_git (vc, files)) {
|
||||
return false;
|
||||
}
|
||||
char *escauth;
|
||||
if (!author) {
|
||||
char *user = r_sys_whoami ();
|
||||
escauth = r_str_escape (user);
|
||||
free (user);
|
||||
} else {
|
||||
escauth = r_str_escape (author);
|
||||
}
|
||||
if (!escauth) {
|
||||
return false;
|
||||
}
|
||||
if (R_STR_ISEMPTY (message)) {
|
||||
R_FREE (message);
|
||||
message = strdup ("default message");
|
||||
}
|
||||
if (R_STR_ISEMPTY (message)) {
|
||||
R_FREE (message);
|
||||
char *epath = r_str_escape (vc->path);
|
||||
if (epath) {
|
||||
// XXX ensure CWD in the same line?
|
||||
int res = r_sys_cmdf ("git -C \"%s\" commit --author \"%s <%s@localhost>\"", epath, escauth, escauth);
|
||||
free (escauth);
|
||||
free (epath);
|
||||
return res == 0;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
char *epath = r_str_escape (vc->path);
|
||||
if (epath) {
|
||||
char *emsg = r_str_escape (message);
|
||||
if (emsg) {
|
||||
int res = r_sys_cmdf ("git -C \"%s\" commit -m \"%s\" --author \"%s <%s@localhost>\"",
|
||||
epath, emsg, escauth, escauth);
|
||||
free (escauth);
|
||||
free (message);
|
||||
free (epath);
|
||||
free (emsg);
|
||||
return res == 0;
|
||||
}
|
||||
}
|
||||
free (message);
|
||||
return false;
|
||||
}
|
||||
|
||||
#if 0
|
||||
R_API RList *rvc_git_get_branches(Rvc *rvc) {
|
||||
r_return_val_if_fail (rvc, NULL);
|
||||
return rvc->p->get_branches (rvc);
|
||||
}
|
||||
|
||||
static bool XXX_git_commit(Rvc *rvc, const char *message, const char *author, const RList *files) {
|
||||
r_return_val_if_fail (rvc && message && author && files, false);
|
||||
if (rvc->p->type == RVC_TYPE_RVC) {
|
||||
#if 0
|
||||
author = author? author : r_config_get (core->config, "cfg.user");
|
||||
#endif
|
||||
r_vc_commit (rvc, message, author, files);
|
||||
return rvc_save (rvc);
|
||||
}
|
||||
return r_vc_git_commit (rvc, message, author, files);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
R_API bool r_vc_git_repo_exists(const RCore *core, const char *path) {
|
||||
char *frp = !strcmp (r_config_get (core->config, "prj.vc.type"), "rvc")?
|
||||
r_file_new (path, ".rvc", NULL):
|
||||
r_file_new (path, ".git", NULL);
|
||||
if (frp) {
|
||||
bool ret = r_file_is_directory (frp);
|
||||
free (frp);
|
||||
return ret;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
R_API RList *branches_git(Rvc *rvc) {
|
||||
RList *ret = NULL;
|
||||
char *esc_path = r_str_escape (rvc->path);
|
||||
if (esc_path) {
|
||||
char *output = r_sys_cmd_strf ("git -C %s branch --color=never", esc_path);
|
||||
r_str_trim (output);
|
||||
free (esc_path);
|
||||
if (!R_STR_ISEMPTY (output)) {
|
||||
ret = r_str_split_duplist (output, "\n", true);
|
||||
RListIter *iter;
|
||||
char *name;
|
||||
r_list_foreach (ret, iter, name) {
|
||||
if (*(char *)iter->data == '*') {
|
||||
iter->data = r_str_new (name + 2);
|
||||
free (name);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static RList *uncommited_git(Rvc *rvc) {
|
||||
RList *ret = NULL;
|
||||
char *esc_path = r_str_escape (rvc->path);
|
||||
if (esc_path) {
|
||||
char *output = r_sys_cmd_strf ("git -C %s status --short",
|
||||
esc_path);
|
||||
free (esc_path);
|
||||
if (!R_STR_ISEMPTY (output)) {
|
||||
r_str_trim(output);
|
||||
ret = r_str_split_duplist (output, "\n", true);
|
||||
free (output);
|
||||
RListIter *iter;
|
||||
char *i;
|
||||
r_list_foreach (ret, iter, i) {
|
||||
//after we add one to the output, there maybe
|
||||
//a space so trim that
|
||||
char *ni = r_str_trim_dup (i + 2);
|
||||
if (!ni) {
|
||||
r_list_free (ret);
|
||||
ret = NULL;
|
||||
break;
|
||||
}
|
||||
free (i);
|
||||
iter->data = ni;
|
||||
}
|
||||
} else {
|
||||
ret = r_list_new ();
|
||||
}
|
||||
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static bool log_git(Rvc *rvc) {
|
||||
bool ret = true;
|
||||
char *esc_path = r_str_escape (rvc->path);
|
||||
if (esc_path) {
|
||||
ret = !r_sys_cmdf ("git -C %s log", esc_path);
|
||||
free (esc_path);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
R_API char *curbranch_git(Rvc *rvc) {
|
||||
char *ret = NULL;
|
||||
char *esc_path = r_str_escape (rvc->path);
|
||||
if (esc_path) {
|
||||
char *branch = r_sys_cmd_strf ("git -C %s rev-parse --abbrev-ref HEAD", esc_path);
|
||||
if (!R_STR_ISEMPTY (branch)) {
|
||||
ret = r_str_ndup (branch, strlen (branch) - 1);
|
||||
}
|
||||
free (branch);
|
||||
free (esc_path);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static bool reset_git(Rvc *rvc) {
|
||||
char *esc_path = r_str_escape (rvc->path);
|
||||
if (esc_path) {
|
||||
bool ret = r_sys_cmdf ("git -C %s checkout .", esc_path);
|
||||
free (esc_path);
|
||||
return !ret;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool clone_git(const Rvc *rvc, const char *dst) {
|
||||
char *esc_src = r_str_escape (rvc->path);
|
||||
char *esc_dst = r_str_escape (dst);
|
||||
bool ret = false;
|
||||
if (esc_src && esc_dst) {
|
||||
ret = !r_sys_cmdf ("git clone %s %s", esc_src, esc_dst);
|
||||
}
|
||||
free (esc_src);
|
||||
free (esc_dst);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void close_git(Rvc *vc, bool save) {
|
||||
if (vc) {
|
||||
free (vc->path);
|
||||
free (vc);
|
||||
}
|
||||
}
|
||||
|
||||
R_API bool save_git(Rvc *vc) {
|
||||
//do nothing, since git commands are automatically executed
|
||||
return true;
|
||||
}
|
||||
|
||||
const RvcPlugin r_vc_plugin_git = {
|
||||
.name = "git",
|
||||
.type = RVC_TYPE_GIT,
|
||||
.commit = commit_git,
|
||||
.branch = _git_branch,
|
||||
.checkout = checkout_git,
|
||||
.branches = branches_git,
|
||||
.uncommited = uncommited_git,
|
||||
.log = log_git,
|
||||
.curbranch = curbranch_git,
|
||||
.reset = reset_git,
|
||||
.clone = clone_git,
|
||||
.close = close_git,
|
||||
.save = save_git,
|
||||
// .init = init_git,
|
||||
.open = open_git,
|
||||
};
|
1235
libr/util/rvc_rvc.c
Normal file
1235
libr/util/rvc_rvc.c
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user