SF.net SVN: geany-plugins:[179] trunk/geanyvc

yurand at users.sourceforge.net yurand at xxxxx
Fri Sep 19 21:29:47 UTC 2008


Revision: 179
          http://geany-plugins.svn.sourceforge.net/geany-plugins/?rev=179&view=rev
Author:   yurand
Date:     2008-09-19 21:29:46 +0000 (Fri, 19 Sep 2008)

Log Message:
-----------
VC: svn diff output is relative to svn base directory now, added unittests

Modified Paths:
--------------
    trunk/geanyvc/Makefile.am
    trunk/geanyvc/configure.in
    trunk/geanyvc/geanyvc.c
    trunk/geanyvc/geanyvc.h
    trunk/geanyvc/po/POTFILES.in
    trunk/geanyvc/vc_bzr.c
    trunk/geanyvc/vc_cvs.c
    trunk/geanyvc/vc_git.c
    trunk/geanyvc/vc_hg.c
    trunk/geanyvc/vc_svk.c
    trunk/geanyvc/vc_svn.c

Added Paths:
-----------
    trunk/geanyvc/po/POTFILES.skip
    trunk/geanyvc/tests/
    trunk/geanyvc/tests/Makefile.am
    trunk/geanyvc/tests/unittests.c
    trunk/geanyvc/utils.c

Modified: trunk/geanyvc/Makefile.am
===================================================================
--- trunk/geanyvc/Makefile.am	2008-09-18 12:13:16 UTC (rev 178)
+++ trunk/geanyvc/Makefile.am	2008-09-19 21:29:46 UTC (rev 179)
@@ -1,5 +1,5 @@
 ## Makefile.am -- Process this file with automake to produce Makefile.in
-SUBDIRS = po
+SUBDIRS = po tests
 
 EXTRA_DIST =				\
 	autogen.sh				\
@@ -16,7 +16,7 @@
 noinst_HEADERS = geanyvc.h
 
 lib_LTLIBRARIES = geanyvc.la
-geanyvc_la_SOURCES = geanyvc.c externdiff.c vc_git.c vc_cvs.c vc_svn.c vc_svk.c vc_bzr.c vc_hg.c
+geanyvc_la_SOURCES = geanyvc.c externdiff.c utils.c vc_git.c vc_cvs.c vc_svn.c vc_svk.c vc_bzr.c vc_hg.c
 geanyvc_la_LDFLAGS = -module -avoid-version
 geanyvc_la_LIBADD  = @GEANY_LIBS@
 

Modified: trunk/geanyvc/configure.in
===================================================================
--- trunk/geanyvc/configure.in	2008-09-18 12:13:16 UTC (rev 178)
+++ trunk/geanyvc/configure.in	2008-09-19 21:29:46 UTC (rev 179)
@@ -81,6 +81,7 @@
 AC_OUTPUT([
 Makefile
 po/Makefile.in
+tests/Makefile
 ])
 
 echo "----------------------------------------"

Modified: trunk/geanyvc/geanyvc.c
===================================================================
--- trunk/geanyvc/geanyvc.c	2008-09-18 12:13:16 UTC (rev 178)
+++ trunk/geanyvc/geanyvc.c	2008-09-19 21:29:46 UTC (rev 179)
@@ -86,12 +86,24 @@
 static GSList *VC = NULL;
 
 /* The addresses of these strings act as enums, their contents are not used. */
-const gchar DIRNAME[] = "*DIRNAME*";
-const gchar FILENAME[] = "*FILENAME*";
+/* absolute path dirname of file */
+const gchar ABS_DIRNAME[] = "*ABS_DIRNAME*";
+/* absolute path filename of file */
+const gchar ABS_FILENAME[] = "*ABS_FILENAME*";;
+
+/* path to directory from base vc directory */
+const gchar BASE_DIRNAME[] = "*BASE_DIRNAME*";
+/* path to file from base vc directory */
 const gchar BASE_FILENAME[] = "*BASE_FILENAME*";
+
+/* basename of file */
+const gchar BASENAME[] = "*BASENAME*";
+/* list with absolute file names*/
 const gchar FILE_LIST[] = "*FILE_LIST*";
+/* message */
 const gchar MESSAGE[] = "*MESSAGE*";
 
+
 /* this string is used when action require to run several commands */
 const gchar CMD_SEPARATOR[] = "*CMD-SEPARATOR*";
 const gchar CMD_FUNCTION[] = "*CUSTOM_FUNCTION*";
@@ -102,8 +114,6 @@
 const gchar FILE_STATUS_DELETED[] = "Deleted";
 const gchar FILE_STATUS_UNKNOWN[] = "Unknown";
 
-void *NO_ENV[] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL };
-
 static void registrate();
 
 GSList *
@@ -238,35 +248,36 @@
 	if (vc)
 	{
 		if (cmd)
-			return vc->commands[cmd_type];
+			return vc->commands[cmd_type].command;
 		else
-			return vc->envs[cmd_type];
+			return vc->commands[cmd_type].env;
 	}
 	return NULL;
 }
 
 /* Get list of commands for given command spec*/
 static GSList *
-get_cmd(const gchar ** argv, const gchar * filename, GSList * filelist, const gchar * message)
+get_cmd(const gchar ** argv, const gchar * dir, const gchar * filename, GSList * filelist,
+	const gchar * message)
 {
 	gint i, j;
 	gint len = 0;
 	gchar **ret;
-	gchar *dir;
+	gchar *abs_dir;
 	gchar *base_filename;
+	gchar *base_dirname;
+	gchar *basename;
 	GSList *head = NULL;
 	GSList *tmp;
 	GString *repl;
 
 	if (g_file_test(filename, G_FILE_TEST_IS_DIR))
-	{
-		dir = g_strdup(filename);
-	}
+		abs_dir = g_strdup(filename);
 	else
-	{
-		dir = g_path_get_dirname(filename);
-	}
-	base_filename = g_path_get_basename(filename);
+		abs_dir = g_path_get_dirname(filename);
+	basename = g_path_get_basename(filename);
+	base_filename = get_relative_path(dir, filename);
+	base_dirname = get_relative_path(dir, abs_dir);
 
 	while (1)
 	{
@@ -294,18 +305,26 @@
 			j = -1;
 			head = g_slist_append(head, ret);
 		}
-		else if (argv[i] == DIRNAME)
+		else if (argv[i] == ABS_DIRNAME)
 		{
-			ret[j] = p_utils->get_locale_from_utf8(dir);
+			ret[j] = p_utils->get_locale_from_utf8(abs_dir);
 		}
-		else if (argv[i] == FILENAME)
+		else if (argv[i] == ABS_FILENAME)
 		{
 			ret[j] = p_utils->get_locale_from_utf8(filename);
 		}
+		else if (argv[i] == BASE_DIRNAME)
+		{
+			ret[j] = p_utils->get_locale_from_utf8(base_dirname);
+		}
 		else if (argv[i] == BASE_FILENAME)
 		{
 			ret[j] = p_utils->get_locale_from_utf8(base_filename);
 		}
+		else if (argv[i] == BASENAME)
+		{
+			ret[j] = p_utils->get_locale_from_utf8(basename);
+		}
 		else if (argv[i] == FILE_LIST)
 		{
 			for (tmp = filelist; tmp != NULL; tmp = g_slist_next(tmp))
@@ -322,15 +341,17 @@
 		else
 		{
 			repl = g_string_new(argv[i]);
-			p_utils->string_replace_all(repl, P_DIRNAME, dir);
-			p_utils->string_replace_all(repl, P_FILENAME, filename);
-			p_utils->string_replace_all(repl, P_BASE_FILENAME, base_filename);
+			p_utils->string_replace_all(repl, P_ABS_DIRNAME, abs_dir);
+			p_utils->string_replace_all(repl, P_ABS_FILENAME, filename);
+			p_utils->string_replace_all(repl, P_BASENAME, basename);
 			ret[j] = g_string_free(repl, FALSE);
 			setptr(ret[j], p_utils->get_locale_from_utf8(ret[j]));
 		}
 	}
-	g_free(dir);
+	g_free(abs_dir);
+	g_free(base_dirname);
 	g_free(base_filename);
+	g_free(basename);
 	return head;
 }
 
@@ -371,6 +392,7 @@
 /*
  * Execute command by command spec, return std_out std_err
  *
+ * @dir - start directory of command
  * @argv - command spec
  * @env - envirounment
  * @std_out - if not NULL here will be returned standard output converted to utf8 of last command in spec
@@ -382,15 +404,16 @@
  * @return - exit code of last command in spec
  */
 gint
-execute_custom_command(const gchar ** argv, const gchar ** env, gchar ** std_out, gchar ** std_err,
-		       const gchar * filename, GSList * list, const gchar * message)
+execute_custom_command(const gchar * dir, const gchar ** argv, const gchar ** env, gchar ** std_out,
+		       gchar ** std_err, const gchar * filename, GSList * list,
+		       const gchar * message)
 {
 	gint exit_code;
-	gchar *dir;
 	GString *tmp;
 	GSList *cur;
-	GSList *largv = get_cmd(argv, filename, list, message);
+	GSList *largv = get_cmd(argv, dir, filename, list, message);
 	GError *error = NULL;
+	printf("%s\n", __FUNCTION__);
 
 	if (std_out)
 		*std_out = NULL;
@@ -402,15 +425,6 @@
 		return 0;
 	}
 
-	if (g_file_test(filename, G_FILE_TEST_IS_DIR))
-	{
-		dir = g_strdup(filename);
-	}
-	else
-	{
-		dir = g_path_get_dirname(filename);
-	}
-
 	for (cur = largv; cur != NULL; cur = g_slist_next(cur))
 	{
 		argv = cur->data;
@@ -479,7 +493,6 @@
 		}
 		g_strfreev(cur->data);
 	}
-	g_free(dir);
 	g_slist_free(largv);
 	return exit_code;
 }
@@ -488,20 +501,39 @@
 execute_command(const VC_RECORD * vc, gchar ** std_out, gchar ** std_err, const gchar * filename,
 		gint cmd, GSList * list, const gchar * message)
 {
+	gchar *dir;
+	gint ret;
+
 	if (std_out)
 		*std_out = NULL;
 	if (std_err)
 		*std_err = NULL;
 
-	if (((gchar **) vc->commands[cmd])[0] == CMD_FUNCTION)
+	if (vc->commands[cmd].function)
 	{
-		typedef gint(*cmd_function) (gchar **, gchar **, const gchar *, GSList *,
-					     const gchar *);
-		return ((cmd_function *) vc->commands[cmd])[1] (std_out, std_err, filename, list,
-								message);
+		return vc->commands[cmd].function(std_out, std_err, filename, list, message);
 	}
-	return execute_custom_command(vc->commands[cmd], vc->envs[cmd], std_out, std_err, filename,
-				      list, message);
+
+	if (vc->commands[cmd].startdir == VC_COMMAND_STARTDIR_FILE)
+	{
+		if (g_file_test(filename, G_FILE_TEST_IS_DIR))
+			dir = g_strdup(filename);
+		else
+			dir = g_path_get_dirname(filename);
+	}
+	else if (vc->commands[cmd].startdir == VC_COMMAND_STARTDIR_BASE)
+	{
+		dir = vc->get_base_dir(filename);
+	}
+	else
+	{
+		fprintf(stderr, "geanyvc: unknown startdir type: %d\n", vc->commands[cmd].startdir);
+	}
+
+	ret = execute_custom_command(dir, vc->commands[cmd].command, vc->commands[cmd].env, std_out,
+				     std_err, filename, list, message);
+	g_free(dir);
+	return ret;
 }
 
 /* Callback if menu item for a single file was activated */
@@ -631,35 +663,38 @@
 }
 
 
-/* Callback if menu item for the current project was activated */
+/* Callback if menu item for the base directory was activated */
 static void
-vcdiff_project_activated(G_GNUC_UNUSED GtkMenuItem * menuitem, G_GNUC_UNUSED gpointer gdata)
+vcdiff_basedir_activated(G_GNUC_UNUSED GtkMenuItem * menuitem, G_GNUC_UNUSED gpointer gdata)
 {
 	gchar *text = NULL;
 	gchar *name;
+	gchar *basedir;
+	gchar *base_name;
 	const VC_RECORD *vc;
 	GeanyDocument *doc;
 
-	GeanyProject *project = geany->app->project;
-
 	doc = p_document->get_current();
+	g_return_if_fail(doc != NULL && doc->file_name != NULL);
 
-	g_return_if_fail(geany->app->project != NULL && NZV(geany->app->project->base_path));
-
 	if (doc && doc->changed && doc->file_name != NULL)
 	{
 		p_document->save_file(doc, FALSE);
 	}
 
-	vc = find_vc(geany->app->project->base_path);
+	vc = find_vc(doc->file_name);
 	g_return_if_fail(vc);
 
-	execute_command(vc, &text, NULL, geany->app->project->base_path, VC_COMMAND_DIFF_DIR, NULL,
-			NULL);
+	basedir = vc->get_base_dir(doc->file_name);
+	g_return_if_fail(basedir);
+
+	execute_command(vc, &text, NULL, basedir, VC_COMMAND_DIFF_DIR, NULL, NULL);
 	if (text)
 	{
-		name = g_strconcat(project->name, ".vc.diff", NULL);
+		base_name = g_path_get_dirname(doc->file_name);
+		name = g_strconcat(base_name, ".vc.diff", NULL);
 		show_output(text, name, NULL);
+		g_free(base_name);
 		g_free(text);
 		g_free(name);
 	}
@@ -667,6 +702,7 @@
 	{
 		p_ui->set_statusbar(FALSE, _("No changes were made."));
 	}
+	g_free(basedir);
 }
 
 static void
@@ -745,24 +781,29 @@
 }
 
 static void
-vclog_project_activated(G_GNUC_UNUSED GtkMenuItem * menuitem, G_GNUC_UNUSED gpointer gdata)
+vclog_basedir_activated(G_GNUC_UNUSED GtkMenuItem * menuitem, G_GNUC_UNUSED gpointer gdata)
 {
 	gchar *text = NULL;
 	const VC_RECORD *vc;
-	GeanyProject *project = geany->app->project;
+	GeanyDocument *doc;
+	gchar *basedir;
 
-	g_return_if_fail(project != NULL && NZV(geany->app->project->base_path));
+	doc = p_document->get_current();
+	g_return_if_fail(doc != NULL && doc->file_name != NULL);
 
-	vc = find_vc(geany->app->project->base_path);
+	vc = find_vc(doc->file_name);
 	g_return_if_fail(vc);
 
-	execute_command(vc, &text, NULL, geany->app->project->base_path, VC_COMMAND_LOG_DIR, NULL,
-			NULL);
+	basedir = vc->get_base_dir(doc->file_name);
+	g_return_if_fail(basedir);
+
+	execute_command(vc, &text, NULL, basedir, VC_COMMAND_LOG_DIR, NULL, NULL);
 	if (text)
 	{
 		show_output(text, "*VC-LOG*", NULL);
 		g_free(text);
 	}
+	g_free(basedir);
 }
 
 /* Show status from the current directory */
@@ -1403,11 +1444,11 @@
 
 static GtkWidget *menu_vc_diff_file = NULL;
 static GtkWidget *menu_vc_diff_dir = NULL;
-static GtkWidget *menu_vc_diff_project = NULL;
+static GtkWidget *menu_vc_diff_basedir = NULL;
 static GtkWidget *menu_vc_blame = NULL;
 static GtkWidget *menu_vc_log_file = NULL;
 static GtkWidget *menu_vc_log_dir = NULL;
-static GtkWidget *menu_vc_log_project = NULL;
+static GtkWidget *menu_vc_log_basedir = NULL;
 static GtkWidget *menu_vc_status = NULL;
 static GtkWidget *menu_vc_revert_file = NULL;
 static GtkWidget *menu_vc_add_file = NULL;
@@ -1418,10 +1459,8 @@
 update_menu_items()
 {
 	GeanyDocument *doc;
-	GeanyProject *project = geany->app->project;
 
 	gboolean have_file;
-	gboolean p_have_vc = FALSE;
 	gboolean d_have_vc = FALSE;
 	gboolean f_have_vc = FALSE;
 
@@ -1441,19 +1480,15 @@
 		g_free(dir);
 	}
 
-	if (project != NULL && NZV(geany->app->project->base_path) &&
-	    find_cmd_env(VC_COMMAND_DIFF_DIR, TRUE, geany->app->project->base_path))
-		p_have_vc = TRUE;
-
 	gtk_widget_set_sensitive(menu_vc_diff_file, f_have_vc);
 	gtk_widget_set_sensitive(menu_vc_diff_dir, d_have_vc);
-	gtk_widget_set_sensitive(menu_vc_diff_project, p_have_vc);
+	gtk_widget_set_sensitive(menu_vc_diff_basedir, d_have_vc);
 
 	gtk_widget_set_sensitive(menu_vc_blame, f_have_vc);
 
 	gtk_widget_set_sensitive(menu_vc_log_file, f_have_vc);
 	gtk_widget_set_sensitive(menu_vc_log_dir, d_have_vc);
-	gtk_widget_set_sensitive(menu_vc_log_project, p_have_vc);
+	gtk_widget_set_sensitive(menu_vc_log_basedir, d_have_vc);
 
 	gtk_widget_set_sensitive(menu_vc_status, d_have_vc);
 
@@ -1782,7 +1817,8 @@
 	REGISTER_VC(HG, enable_hg);
 }
 
-static void locale_init(void)
+static void
+locale_init(void)
 {
 #ifdef ENABLE_NLS
 	gchar *locale_dir = NULL;
@@ -1853,13 +1889,13 @@
 			 G_CALLBACK(vcdiff_dir_activated), NULL);
 
 	// Project
-	menu_vc_diff_project = gtk_menu_item_new_with_mnemonic(_("Diff From Current Project"));
-	gtk_container_add(GTK_CONTAINER(menu_vc_menu), menu_vc_diff_project);
-	gtk_tooltips_set_tip(tooltips, menu_vc_diff_project,
-			     _("Make a diff from the current project's base path"), NULL);
+	menu_vc_diff_basedir = gtk_menu_item_new_with_mnemonic(_("Diff From Base Directory"));
+	gtk_container_add(GTK_CONTAINER(menu_vc_menu), menu_vc_diff_basedir);
+	gtk_tooltips_set_tip(tooltips, menu_vc_diff_basedir,
+			     _("Make a diff from the top VC directory"), NULL);
 
-	g_signal_connect((gpointer) menu_vc_diff_project, "activate",
-			 G_CALLBACK(vcdiff_project_activated), NULL);
+	g_signal_connect((gpointer) menu_vc_diff_basedir, "activate",
+			 G_CALLBACK(vcdiff_basedir_activated), NULL);
 
 	gtk_container_add(GTK_CONTAINER(menu_vc_menu), gtk_separator_menu_item_new());
 
@@ -1891,13 +1927,13 @@
 	g_signal_connect((gpointer) menu_vc_log_dir, "activate",
 			 G_CALLBACK(vclog_dir_activated), NULL);
 
-	menu_vc_log_project = gtk_menu_item_new_with_mnemonic(_("Log Of Current Project"));
-	gtk_container_add(GTK_CONTAINER(menu_vc_menu), menu_vc_log_project);
-	gtk_tooltips_set_tip(tooltips, menu_vc_log_project,
-			     _("Shows the log of the current project"), NULL);
+	menu_vc_log_basedir = gtk_menu_item_new_with_mnemonic(_("Log Of Base Directory"));
+	gtk_container_add(GTK_CONTAINER(menu_vc_menu), menu_vc_log_basedir);
+	gtk_tooltips_set_tip(tooltips, menu_vc_log_basedir,
+			     _("Shows the log of the top VC directory"), NULL);
 
-	g_signal_connect((gpointer) menu_vc_log_project, "activate",
-			 G_CALLBACK(vclog_project_activated), NULL);
+	g_signal_connect((gpointer) menu_vc_log_basedir, "activate",
+			 G_CALLBACK(vclog_basedir_activated), NULL);
 
 	gtk_container_add(GTK_CONTAINER(menu_vc_menu), gtk_separator_menu_item_new());
 

Modified: trunk/geanyvc/geanyvc.h
===================================================================
--- trunk/geanyvc/geanyvc.h	2008-09-18 12:13:16 UTC (rev 178)
+++ trunk/geanyvc/geanyvc.h	2008-09-19 21:29:46 UTC (rev 179)
@@ -38,20 +38,47 @@
 	VC_COMMAND_COUNT
 };
 
-#define P_DIRNAME "*<?geanyvcDIRNAME>*"
-#define P_FILENAME "*<?geanyvcFILENAME>*"
-#define P_BASE_FILENAME "*<?geanyvcBASE_FILENAME>*"
+/*
+ * VC_COMMAND_STARTDIR_BASE - command strat dir will be VC base directory
+ * VC_COMMAND_STARTDIR_FILE - command start dir will be taken as basename
+ *                            of file, or directory itself if file is
+ *                            directory
+ */
+enum
+{
+	VC_COMMAND_STARTDIR_BASE,
+	VC_COMMAND_STARTDIR_FILE
+};
 
+#define P_ABS_DIRNAME "*<?geanyvcDIRNAME>*"
+#define P_ABS_FILENAME "*<?geanyvcFILENAME>*"
+#define P_BASENAME "*<?geanyvcBASE_FILENAME>*"
+
 /* The addresses of these strings act as enums, their contents are not used. */
-extern const gchar DIRNAME[];
-extern const gchar FILENAME[];
+
+
+/* absolute path dirname of file */
+extern const gchar ABS_DIRNAME[];
+/* absolute path filename of file */
+extern const gchar ABS_FILENAME[];
+
+/* path to directory from base vc directory */
+extern const gchar BASE_DIRNAME[];
+/* path to file from base vc directory */
 extern const gchar BASE_FILENAME[];
+
+/* basename of file */
+extern const gchar BASENAME[];
+/* list with absolute file names*/
 extern const gchar FILE_LIST[];
+/* message */
 extern const gchar MESSAGE[];
 
+
+
+
 /* this string is used when action require to run several commands */
 extern const gchar CMD_SEPARATOR[];
-extern const gchar CMD_FUNCTION[];
 
 extern const gchar FILE_STATUS_MODIFIED[];
 extern const gchar FILE_STATUS_ADDED[];
@@ -59,17 +86,26 @@
 extern const gchar FILE_STATUS_UNKNOWN[];
 
 gint
-execute_custom_command(const gchar ** argv, const gchar ** env, gchar ** std_out, gchar ** std_err,
-		       const gchar * filename, GSList * list, const gchar * message);
+execute_custom_command(const gchar * dir, const gchar ** argv, const gchar ** env, gchar ** std_out,
+		       gchar ** std_err, const gchar * filename, GSList * list,
+		       const gchar * message);
 
 gboolean find_dir(const gchar * filename, const char *find, gboolean recursive);
 gchar *find_subdir_path(const gchar * filename, const gchar * subdir);
 
+typedef struct _VC_COMMAND
+{
+	gint startdir;
+	const gchar **command;
+	const gchar **env;
+	  gint(*function) (gchar **, gchar **, const gchar *, GSList *, const gchar *);
+} VC_COMMAND;
+
 typedef struct _VC_RECORD
 {
-	void **commands;
-	void **envs;
+	const VC_COMMAND *commands;
 	const gchar *program;
+	gchar *(*get_base_dir) (const gchar * path);
 	  gboolean(*in_vc) (const gchar * path);	// check if file in VC
 	GSList *(*get_commit_files) (const gchar * dir);
 } VC_RECORD;
@@ -85,10 +121,16 @@
 
 /* Blank functions and values */
 GSList *get_commit_files_null(const gchar * dir);
-extern void *NO_ENV[];
+extern const gchar *NO_ENV[];
 
 /* External diff viewer */
 const gchar *get_external_diff_viewer();
 void vc_external_diff(const gchar * src, const gchar * dest);
 
+/* utils.c */
+gchar *normpath(const gchar * filename);
+gchar *get_full_path(const gchar * location, const gchar * path);
+gchar *get_relative_path(const gchar * location, const gchar * path);
+
+
 #endif // __GEANYVC_HEADER__

Modified: trunk/geanyvc/po/POTFILES.in
===================================================================
--- trunk/geanyvc/po/POTFILES.in	2008-09-18 12:13:16 UTC (rev 178)
+++ trunk/geanyvc/po/POTFILES.in	2008-09-19 21:29:46 UTC (rev 179)
@@ -5,4 +5,5 @@
 vc_git.c
 vc_hg.c
 vc_svk.c
-vc_svn.c
\ No newline at end of file
+vc_svn.c
+utils.c

Added: trunk/geanyvc/po/POTFILES.skip
===================================================================
--- trunk/geanyvc/po/POTFILES.skip	                        (rev 0)
+++ trunk/geanyvc/po/POTFILES.skip	2008-09-19 21:29:46 UTC (rev 179)
@@ -0,0 +1 @@
+commit.glade

Added: trunk/geanyvc/tests/Makefile.am
===================================================================
--- trunk/geanyvc/tests/Makefile.am	                        (rev 0)
+++ trunk/geanyvc/tests/Makefile.am	2008-09-19 21:29:46 UTC (rev 179)
@@ -0,0 +1,15 @@
+## Makefile.am -- Process this file with automake to produce Makefile.in
+#SUBDIRS = tests
+
+INCLUDES = -I..
+
+if UNITTESTS
+TESTS=unittests
+noinst_PROGRAMS=unittests
+unittests_SOURCES = unittests.c \
+	../utils.c
+
+AM_CFLAGS = @CHECK_CFLAGS@ @GEANY_CFLAGS@ -DLOCALEDIR=\""$(localedir)"\" -DUNITTESTS
+
+unittests_LDADD  = @GEANY_LIBS@ $(INTLLIBS) @CHECK_LIBS@
+endif

Added: trunk/geanyvc/tests/unittests.c
===================================================================
--- trunk/geanyvc/tests/unittests.c	                        (rev 0)
+++ trunk/geanyvc/tests/unittests.c	2008-09-19 21:29:46 UTC (rev 179)
@@ -0,0 +1,30 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <check.h>
+#include <string.h>
+
+#include <gtk/gtk.h>
+#include "geany.h"
+
+extern TCase *utils_test_case_create();
+
+Suite *
+my_suite(void)
+{
+	Suite *s = suite_create("VC");
+	TCase *tc_utils = utils_test_case_create();
+	suite_add_tcase(s, tc_utils);
+	return s;
+}
+
+int
+main(void)
+{
+	int nf;
+	Suite *s = my_suite();
+	SRunner *sr = srunner_create(s);
+	srunner_run_all(sr, CK_NORMAL);
+	nf = srunner_ntests_failed(sr);
+	srunner_free(sr);
+	return (nf == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
+}

Added: trunk/geanyvc/utils.c
===================================================================
--- trunk/geanyvc/utils.c	                        (rev 0)
+++ trunk/geanyvc/utils.c	2008-09-19 21:29:46 UTC (rev 179)
@@ -0,0 +1,171 @@
+/*
+ *
+ *  Copyright 2008 Yura Siamashka <yurand2 at gmail.com>
+ *
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <string.h>
+#include <glib.h>
+
+#include "geany.h"
+#include "utils.h"
+#include "plugindata.h"
+#include "pluginmacros.h"
+
+extern GeanyData *geany_data;
+extern GeanyFunctions *geany_functions;
+
+
+/* Normalize a pathname. This collapses redundant separators and up-level references so that A//B, A/./B
+ * and A/foo/../B all become A/B. It does not normalize the case. On Windows, it converts forward
+ * slashes to backward slashes. It should be understood that this may change the meaning of the
+ * path if it contains symbolic links!
+ */
+gchar *
+normpath(const gchar * filename)
+{
+	gchar **v;
+	gchar **p;
+	gchar **out;
+	gchar **pout;
+	gchar *ret;
+
+	if (!filename || strlen(filename) == 0)
+		return g_strdup(".");
+	v = g_strsplit_set(filename, "/\\", -1);
+	if (!g_strv_length(v))
+		return g_strdup(".");
+
+	out = g_malloc0(sizeof(gchar *) * (g_strv_length(v) + 2));
+	pout = out;
+
+	if (filename[0] == '.' && strcmp(v[0], ".") == 0)
+	{
+		*pout = strdup(".");
+		pout++;
+	}
+	else if (filename[0] == '/')
+	{
+		*pout = strdup("/");
+		pout++;
+	}
+
+	for (p = v; *p; p++)
+	{
+		if (strcmp(*p, ".") == 0 || strcmp(*p, "") == 0)
+		{
+			continue;
+		}
+		else if (strcmp(*p, "..") == 0)
+		{
+			if (pout != out)
+			{
+				pout--;
+				if (strcmp(*pout, "..") != 0)
+				{
+					g_free(*pout);
+					*pout = NULL;
+					continue;
+				}
+				pout++;
+			}
+		}
+		*pout++ = g_strdup(*p);
+	}
+
+	ret = g_build_filenamev(out);
+
+	g_strfreev(out);
+	g_strfreev(v);
+	return ret;
+}
+
+gchar *
+get_full_path(const gchar * location, const gchar * path)
+{
+	gchar *dir;
+
+	dir = g_path_get_dirname(location);
+	setptr(dir, g_build_filename(dir, path, NULL));
+	setptr(dir, normpath(dir));
+	return dir;
+}
+
+gchar *
+get_relative_path(const gchar * location, const gchar * path)
+{
+	gchar *dir;
+	gchar *pth;
+	gchar *ret = NULL;
+
+	gint plen;
+	gint dlen;
+
+	if (!g_path_is_absolute(path))
+	{
+		return g_strdup(path);
+	}
+
+	dir = normpath(location);
+	pth = normpath(path);
+
+	plen = strlen(pth);
+	dlen = strlen(dir);
+
+	if (strstr(pth, dir) == pth)
+	{
+		if (plen > dlen)
+		{
+			ret = g_strdup(path + strlen(dir) + 1);
+		}
+		else if (plen == dlen)
+		{
+			ret = g_strdup(".");
+		}
+	}
+	g_free(dir);
+	g_free(pth);
+	return ret;
+}
+
+
+#ifdef UNITTESTS
+#include <check.h>
+
+START_TEST(test_get_relative_path)
+{
+	gchar *path;
+	path = get_relative_path("/a/b", "/a/b/c");
+	fail_unless(strcmp(path, "c") == 0, "expected: \"c\", get \"%s\"\n", path);
+	g_free(path);
+
+	path = get_relative_path("/a/b", "/a/b");
+	fail_unless(strcmp(path, ".") == 0, "expected: \".\", get \"%s\"\n", path);
+	g_free(path);
+}
+
+END_TEST;
+
+
+TCase *
+utils_test_case_create()
+{
+	TCase *tc_utils = tcase_create("utils");
+	tcase_add_test(tc_utils, test_get_relative_path);
+	return tc_utils;
+}
+
+
+#endif

Modified: trunk/geanyvc/vc_bzr.c
===================================================================
--- trunk/geanyvc/vc_bzr.c	2008-09-18 12:13:16 UTC (rev 178)
+++ trunk/geanyvc/vc_bzr.c	2008-09-19 21:29:46 UTC (rev 179)
@@ -35,31 +35,83 @@
 extern GeanyData *geany_data;
 
 
-static const gchar *BZR_CMD_DIFF_FILE[] = { "bzr", "diff", BASE_FILENAME, NULL };
-static const gchar *BZR_CMD_DIFF_DIR[] = { "bzr", "diff", DIRNAME, NULL };
-static const gchar *BZR_CMD_REVERT_FILE[] = { "bzr", "revert", BASE_FILENAME, NULL };
+static const gchar *BZR_CMD_DIFF_FILE[] = { "bzr", "diff", BASENAME, NULL };
+static const gchar *BZR_CMD_DIFF_DIR[] = { "bzr", "diff", ABS_DIRNAME, NULL };
+static const gchar *BZR_CMD_REVERT_FILE[] = { "bzr", "revert", BASENAME, NULL };
 static const gchar *BZR_CMD_STATUS[] = { "bzr", "status", NULL };
-static const gchar *BZR_CMD_ADD[] = { "bzr", "add", BASE_FILENAME, NULL };
-static const gchar *BZR_CMD_REMOVE[] = { "bzr", "remove", BASE_FILENAME, NULL };
-static const gchar *BZR_CMD_LOG_FILE[] = { "bzr", "log", BASE_FILENAME, NULL };
-static const gchar *BZR_CMD_LOG_DIR[] = { "bzr", "log", DIRNAME, NULL };
+static const gchar *BZR_CMD_ADD[] = { "bzr", "add", BASENAME, NULL };
+static const gchar *BZR_CMD_REMOVE[] = { "bzr", "remove", BASENAME, NULL };
+static const gchar *BZR_CMD_LOG_FILE[] = { "bzr", "log", BASENAME, NULL };
+static const gchar *BZR_CMD_LOG_DIR[] = { "bzr", "log", ABS_DIRNAME, NULL };
 static const gchar *BZR_CMD_COMMIT[] = { "bzr", "commit", "-m", MESSAGE, FILE_LIST, NULL };
-static const gchar *BZR_CMD_BLAME[] = { "bzr", "blame", "--all", "--long", BASE_FILENAME, NULL };
-static const gchar *BZR_CMD_SHOW[] = { "bzr", "cat", BASE_FILENAME, NULL };
+static const gchar *BZR_CMD_BLAME[] = { "bzr", "blame", "--all", "--long", BASENAME, NULL };
+static const gchar *BZR_CMD_SHOW[] = { "bzr", "cat", BASENAME, NULL };
 
-static void *BZR_COMMANDS[VC_COMMAND_COUNT] = { BZR_CMD_DIFF_FILE,
-	BZR_CMD_DIFF_DIR,
-	BZR_CMD_REVERT_FILE,
-	BZR_CMD_STATUS,
-	BZR_CMD_ADD,
-	BZR_CMD_REMOVE,
-	BZR_CMD_LOG_FILE,
-	BZR_CMD_LOG_DIR,
-	BZR_CMD_COMMIT,
-	BZR_CMD_BLAME,
-	BZR_CMD_SHOW
+static const VC_COMMAND commands[] = {
+	{
+	 .startdir = VC_COMMAND_STARTDIR_FILE,
+	 .command = BZR_CMD_DIFF_FILE,
+	 .env = NULL,
+	 .function = NULL},
+	{
+	 .startdir = VC_COMMAND_STARTDIR_FILE,
+	 .command = BZR_CMD_DIFF_DIR,
+	 .env = NULL,
+	 .function = NULL},
+	{
+	 .startdir = VC_COMMAND_STARTDIR_FILE,
+	 .command = BZR_CMD_REVERT_FILE,
+	 .env = NULL,
+	 .function = NULL},
+	{
+	 .startdir = VC_COMMAND_STARTDIR_FILE,
+	 .command = BZR_CMD_STATUS,
+	 .env = NULL,
+	 .function = NULL},
+	{
+	 .startdir = VC_COMMAND_STARTDIR_FILE,
+	 .command = BZR_CMD_ADD,
+	 .env = NULL,
+	 .function = NULL},
+	{
+	 .startdir = VC_COMMAND_STARTDIR_FILE,
+	 .command = BZR_CMD_REMOVE,
+	 .env = NULL,
+	 .function = NULL},
+	{
+	 .startdir = VC_COMMAND_STARTDIR_FILE,
+	 .command = BZR_CMD_LOG_FILE,
+	 .env = NULL,
+	 .function = NULL},
+	{
+	 .startdir = VC_COMMAND_STARTDIR_FILE,
+	 .command = BZR_CMD_LOG_DIR,
+	 .env = NULL,
+	 .function = NULL},
+	{
+	 .startdir = VC_COMMAND_STARTDIR_FILE,
+	 .command = BZR_CMD_COMMIT,
+	 .env = NULL,
+	 .function = NULL},
+	{
+	 .startdir = VC_COMMAND_STARTDIR_FILE,
+	 .command = BZR_CMD_BLAME,
+	 .env = NULL,
+	 .function = NULL},
+	{
+	 .startdir = VC_COMMAND_STARTDIR_FILE,
+	 .command = BZR_CMD_SHOW,
+	 .env = NULL,
+	 .function = NULL}
 };
 
+
+static gchar *
+get_base_dir(const gchar * path)
+{
+	return find_subdir_path(path, ".bzr");
+}
+
 static gboolean
 in_vc_bzr(const gchar * filename)
 {
@@ -80,7 +132,7 @@
 	base_name = g_path_get_basename(filename);
 	argv[2] = base_name;
 
-	exit_code = execute_custom_command((const gchar **) argv, NULL, &std_output, NULL,
+	exit_code = execute_custom_command(dir, (const gchar **) argv, NULL, &std_output, NULL,
 					   dir, NULL, NULL);
 
 	if (NZV(std_output))
@@ -123,7 +175,7 @@
 
 	g_return_val_if_fail(base_dir, NULL);
 
-	execute_custom_command(argv, NULL, &txt, NULL, base_dir, NULL, NULL);
+	execute_custom_command(base_dir, argv, NULL, &txt, NULL, base_dir, NULL, NULL);
 	if (!NZV(txt))
 	{
 		g_free(base_dir);
@@ -207,4 +259,10 @@
 	return ret;
 }
 
-VC_RECORD VC_BZR = { BZR_COMMANDS, NO_ENV, "bzr", in_vc_bzr, get_commit_files_bzr };
+VC_RECORD VC_BZR = {
+	.commands = commands,
+	.program = "bzr",
+	.get_base_dir = get_base_dir,
+	.in_vc = in_vc_bzr,
+	.get_commit_files = get_commit_files_bzr,
+};

Modified: trunk/geanyvc/vc_cvs.c
===================================================================
--- trunk/geanyvc/vc_cvs.c	2008-09-18 12:13:16 UTC (rev 178)
+++ trunk/geanyvc/vc_cvs.c	2008-09-19 21:29:46 UTC (rev 179)
@@ -40,25 +40,82 @@
 static const gchar *CVS_CMD_LOG_DIR[] = { "cvs", "log", NULL };
 static const gchar *CVS_CMD_COMMIT[] = { "cvs", NULL };
 static const gchar *CVS_CMD_BLAME[] = { "cvs", "annotate", BASE_FILENAME, NULL };
+static const gchar *CVS_CMD_SHOW[] = { "cvs", NULL };
 
-static void *CVS_COMMANDS[VC_COMMAND_COUNT] = { CVS_CMD_DIFF_FILE,
-	CVS_CMD_DIFF_DIR,
-	CVS_CMD_REVERT_FILE,
-	CVS_CMD_STATUS,
-	CVS_CMD_ADD,
-	CVS_CMD_REMOVE,
-	CVS_CMD_LOG_FILE,
-	CVS_CMD_LOG_DIR,
-	CVS_CMD_COMMIT,
-	CVS_CMD_BLAME,
-	NULL
+static const VC_COMMAND commands[] = {
+	{
+	 .startdir = VC_COMMAND_STARTDIR_FILE,
+	 .command = CVS_CMD_DIFF_FILE,
+	 .env = NULL,
+	 .function = NULL},
+	{
+	 .startdir = VC_COMMAND_STARTDIR_FILE,
+	 .command = CVS_CMD_DIFF_DIR,
+	 .env = NULL,
+	 .function = NULL},
+	{
+	 .startdir = VC_COMMAND_STARTDIR_FILE,
+	 .command = CVS_CMD_REVERT_FILE,
+	 .env = NULL,
+	 .function = NULL},
+	{
+	 .startdir = VC_COMMAND_STARTDIR_FILE,
+	 .command = CVS_CMD_STATUS,
+	 .env = NULL,
+	 .function = NULL},
+	{
+	 .startdir = VC_COMMAND_STARTDIR_FILE,
+	 .command = CVS_CMD_ADD,
+	 .env = NULL,
+	 .function = NULL},
+	{
+	 .startdir = VC_COMMAND_STARTDIR_FILE,
+	 .command = CVS_CMD_REMOVE,
+	 .env = NULL,
+	 .function = NULL},
+	{
+	 .startdir = VC_COMMAND_STARTDIR_FILE,
+	 .command = CVS_CMD_LOG_FILE,
+	 .env = NULL,
+	 .function = NULL},
+	{
+	 .startdir = VC_COMMAND_STARTDIR_FILE,
+	 .command = CVS_CMD_LOG_DIR,
+	 .env = NULL,
+	 .function = NULL},
+	{
+	 .startdir = VC_COMMAND_STARTDIR_FILE,
+	 .command = CVS_CMD_COMMIT,
+	 .env = NULL,
+	 .function = NULL},
+	{
+	 .startdir = VC_COMMAND_STARTDIR_FILE,
+	 .command = CVS_CMD_BLAME,
+	 .env = NULL,
+	 .function = NULL},
+	{
+	 .startdir = VC_COMMAND_STARTDIR_FILE,
+	 .command = CVS_CMD_SHOW,
+	 .env = NULL,
+	 .function = NULL}
 };
 
+static gchar *
+get_base_dir(const gchar * path)
+{
+	return find_subdir_path(path, "CVS");
+}
+
 static gboolean
 in_vc_cvs(const gchar * filename)
 {
 	return find_dir(filename, "CVS", FALSE);
 }
 
-
-VC_RECORD VC_CVS = { CVS_COMMANDS, NO_ENV, "cvs", in_vc_cvs, get_commit_files_null };
+VC_RECORD VC_CVS = {
+	.commands = commands,
+	.program = "cvs",
+	.get_base_dir = get_base_dir,
+	.in_vc = in_vc_cvs,
+	.get_commit_files = get_commit_files_null,
+};

Modified: trunk/geanyvc/vc_git.c
===================================================================
--- trunk/geanyvc/vc_git.c	2008-09-18 12:13:16 UTC (rev 178)
+++ trunk/geanyvc/vc_git.c	2008-09-19 21:29:46 UTC (rev 179)
@@ -34,12 +34,17 @@
 
 extern GeanyData *geany_data;
 
+static gchar *
+get_base_dir(const gchar * path)
+{
+	return find_subdir_path(path, ".git");
+}
 
 static gint
 git_commit(G_GNUC_UNUSED gchar ** std_out, G_GNUC_UNUSED gchar ** std_err, const gchar * filename,
 	   GSList * list, const gchar * message)
 {
-	gchar *base_dir = find_subdir_path(filename, ".git");
+	gchar *base_dir = get_base_dir(filename);
 	gint len = strlen(base_dir);
 	GSList *commit = NULL;
 	GSList *tmp = NULL;
@@ -53,7 +58,7 @@
 		commit = g_slist_prepend(commit, (gchar *) tmp->data + len + 1);
 	}
 
-	ret = execute_custom_command(argv, NULL, NULL, NULL, base_dir, commit, message);
+	ret = execute_custom_command(base_dir, argv, NULL, NULL, NULL, base_dir, commit, message);
 	g_slist_free(commit);
 	g_free(base_dir);
 	return ret;
@@ -64,7 +69,7 @@
 git_show(gchar ** std_out, gchar ** std_err, const gchar * filename,
 	 GSList * list, const gchar * message)
 {
-	gchar *base_dir = find_subdir_path(filename, ".git");
+	gchar *base_dir = get_base_dir(filename);
 	gint len = strlen(base_dir);
 	const gchar *argv[] = { "git", "show", NULL, NULL };
 	gint ret;
@@ -73,7 +78,8 @@
 
 	argv[2] = g_strdup_printf("HEAD:%s", filename + len + 1);
 
-	ret = execute_custom_command(argv, GIT_ENV_SHOW, std_out, std_err, base_dir, list, message);
+	ret = execute_custom_command(base_dir, argv, GIT_ENV_SHOW, std_out, std_err, base_dir, list,
+				     message);
 	g_free(base_dir);
 	g_free((gchar *) argv[2]);
 	return ret;
@@ -81,20 +87,18 @@
 
 
 
-static const gchar *GIT_CMD_DIFF_FILE[] = { "git", "diff", "HEAD", "--", BASE_FILENAME, NULL };
+static const gchar *GIT_CMD_DIFF_FILE[] = { "git", "diff", "HEAD", "--", BASENAME, NULL };
 static const gchar *GIT_CMD_DIFF_DIR[] = { "git", "diff", "HEAD", NULL };
-static const gchar *GIT_CMD_REVERT_FILE[] = { "git", "checkout", "--", BASE_FILENAME, NULL };
+static const gchar *GIT_CMD_REVERT_FILE[] = { "git", "checkout", "--", BASENAME, NULL };
 static const gchar *GIT_CMD_STATUS[] = { "git", "status", NULL };
-static const gchar *GIT_CMD_ADD[] = { "git", "add", "--", BASE_FILENAME, NULL };
+static const gchar *GIT_CMD_ADD[] = { "git", "add", "--", BASENAME, NULL };
 static const gchar *GIT_CMD_REMOVE[] =
-	{ "git", "rm", "-f", "--", BASE_FILENAME, CMD_SEPARATOR, "git", "reset", "HEAD", "--",
-	BASE_FILENAME, NULL
+	{ "git", "rm", "-f", "--", BASENAME, CMD_SEPARATOR, "git", "reset", "HEAD", "--",
+	BASENAME, NULL
 };
-static const gchar *GIT_CMD_LOG_FILE[] = { "git", "log", "--", BASE_FILENAME, NULL };
+static const gchar *GIT_CMD_LOG_FILE[] = { "git", "log", "--", BASENAME, NULL };
 static const gchar *GIT_CMD_LOG_DIR[] = { "git", "log", NULL };
-static const void *GIT_CMD_COMMIT[] = { CMD_FUNCTION, git_commit };
-static const gchar *GIT_CMD_BLAME[] = { "git", "blame", "--", BASE_FILENAME, NULL };
-static const void *GIT_CMD_SHOW[] = { CMD_FUNCTION, git_show };
+static const gchar *GIT_CMD_BLAME[] = { "git", "blame", "--", BASENAME, NULL };
 
 static const gchar *GIT_ENV_DIFF_FILE[] = { "PAGER=cat", NULL };
 static const gchar *GIT_ENV_DIFF_DIR[] = { "PAGER=cat", NULL };
@@ -106,34 +110,64 @@
 static const gchar *GIT_ENV_LOG_DIR[] = { "PAGER=cat", NULL };
 static const gchar *GIT_ENV_BLAME[] = { "PAGER=cat", NULL };
 
-#define GIT_ENV_COMMIT NULL
-
-static void *GIT_COMMANDS[VC_COMMAND_COUNT] = { GIT_CMD_DIFF_FILE,
-	GIT_CMD_DIFF_DIR,
-	GIT_CMD_REVERT_FILE,
-	GIT_CMD_STATUS,
-	GIT_CMD_ADD,
-	GIT_CMD_REMOVE,
-	GIT_CMD_LOG_FILE,
-	GIT_CMD_LOG_DIR,
-	GIT_CMD_COMMIT,
-	GIT_CMD_BLAME,
-	GIT_CMD_SHOW
+static const VC_COMMAND commands[] = {
+	{
+	 .startdir = VC_COMMAND_STARTDIR_FILE,
+	 .command = GIT_CMD_DIFF_FILE,
+	 .env = GIT_ENV_DIFF_FILE,
+	 .function = NULL},
+	{
+	 .startdir = VC_COMMAND_STARTDIR_FILE,
+	 .command = GIT_CMD_DIFF_DIR,
+	 .env = GIT_ENV_DIFF_DIR,
+	 .function = NULL},
+	{
+	 .startdir = VC_COMMAND_STARTDIR_FILE,
+	 .command = GIT_CMD_REVERT_FILE,
+	 .env = GIT_ENV_REVERT_FILE,
+	 .function = NULL},
+	{
+	 .startdir = VC_COMMAND_STARTDIR_FILE,
+	 .command = GIT_CMD_STATUS,
+	 .env = GIT_ENV_STATUS,
+	 .function = NULL},
+	{
+	 .startdir = VC_COMMAND_STARTDIR_FILE,
+	 .command = GIT_CMD_ADD,
+	 .env = GIT_ENV_ADD,
+	 .function = NULL},
+	{
+	 .startdir = VC_COMMAND_STARTDIR_FILE,
+	 .command = GIT_CMD_REMOVE,
+	 .env = GIT_ENV_REMOVE,
+	 .function = NULL},
+	{
+	 .startdir = VC_COMMAND_STARTDIR_FILE,
+	 .command = GIT_CMD_LOG_FILE,
+	 .env = GIT_ENV_LOG_FILE,
+	 .function = NULL},
+	{
+	 .startdir = VC_COMMAND_STARTDIR_FILE,
+	 .command = GIT_CMD_LOG_DIR,
+	 .env = GIT_ENV_LOG_DIR,
+	 .function = NULL},
+	{
+	 .startdir = VC_COMMAND_STARTDIR_FILE,
+	 .command = NULL,
+	 .env = NULL,
+	 .function = git_commit},
+	{
+	 .startdir = VC_COMMAND_STARTDIR_FILE,
+	 .command = GIT_CMD_BLAME,
+	 .env = GIT_ENV_BLAME,
+	 .function = NULL},
+	{
+	 .startdir = VC_COMMAND_STARTDIR_FILE,
+	 .command = NULL,
+	 .env = GIT_ENV_SHOW,
+	 .function = git_show}
 };
 
-static void *GIT_ENV[] = { GIT_ENV_DIFF_FILE,
-	GIT_ENV_DIFF_DIR,
-	GIT_ENV_REVERT_FILE,
-	GIT_ENV_STATUS,
-	GIT_ENV_ADD,
-	GIT_ENV_REMOVE,
-	GIT_ENV_LOG_FILE,
-	GIT_ENV_LOG_DIR,
-	GIT_ENV_COMMIT,
-	GIT_ENV_BLAME,
-	GIT_ENV_SHOW
-};
-
 static gboolean
 in_vc_git(const gchar * filename)
 {
@@ -154,7 +188,7 @@
 	base_name = g_path_get_basename(filename);
 	argv[3] = base_name;
 
-	exit_code = execute_custom_command((const gchar **) argv, NULL, &std_output, NULL,
+	exit_code = execute_custom_command(dir, (const gchar **) argv, NULL, &std_output, NULL,
 					   dir, NULL, NULL);
 	if (NZV(std_output))
 	{
@@ -218,8 +252,8 @@
 	g_return_val_if_fail(base_dir, NULL);
 
 	exit_code =
-		execute_custom_command((const gchar **) argv, (const gchar **) env, &std_out, NULL,
-				       base_dir, NULL, NULL);
+		execute_custom_command(base_dir, (const gchar **) argv, (const gchar **) env,
+				       &std_out, NULL, base_dir, NULL, NULL);
 	g_return_val_if_fail(std_out, NULL);
 
 	ret = parse_git_status(ret, base_dir, std_out, "modified:", FILE_STATUS_MODIFIED);
@@ -232,4 +266,10 @@
 	return ret;
 }
 
-VC_RECORD VC_GIT = { GIT_COMMANDS, GIT_ENV, "git", in_vc_git, get_commit_files_git };
+VC_RECORD VC_GIT = {
+	.commands = commands,
+	.program = "git",
+	.get_base_dir = get_base_dir,
+	.in_vc = in_vc_git,
+	.get_commit_files = get_commit_files_git,
+};

Modified: trunk/geanyvc/vc_hg.c
===================================================================
--- trunk/geanyvc/vc_hg.c	2008-09-18 12:13:16 UTC (rev 178)
+++ trunk/geanyvc/vc_hg.c	2008-09-19 21:29:46 UTC (rev 179)
@@ -35,31 +35,82 @@
 extern GeanyData *geany_data;
 
 
-static const gchar *HG_CMD_DIFF_FILE[] = { "hg", "diff", FILENAME, NULL };
-static const gchar *HG_CMD_DIFF_DIR[] = { "hg", "diff", DIRNAME, NULL };
-static const gchar *HG_CMD_REVERT_FILE[] = { "hg", "revert", BASE_FILENAME, NULL };
+static const gchar *HG_CMD_DIFF_FILE[] = { "hg", "diff", ABS_FILENAME, NULL };
+static const gchar *HG_CMD_DIFF_DIR[] = { "hg", "diff", ABS_DIRNAME, NULL };
+static const gchar *HG_CMD_REVERT_FILE[] = { "hg", "revert", BASENAME, NULL };
 static const gchar *HG_CMD_STATUS[] = { "hg", "status", NULL };
-static const gchar *HG_CMD_ADD[] = { "hg", "add", BASE_FILENAME, NULL };
-static const gchar *HG_CMD_REMOVE[] = { "hg", "remove", BASE_FILENAME, NULL };
-static const gchar *HG_CMD_LOG_FILE[] = { "hg", "log", BASE_FILENAME, NULL };
-static const gchar *HG_CMD_LOG_DIR[] = { "hg", "log", DIRNAME, NULL };
+static const gchar *HG_CMD_ADD[] = { "hg", "add", BASENAME, NULL };
+static const gchar *HG_CMD_REMOVE[] = { "hg", "remove", BASENAME, NULL };
+static const gchar *HG_CMD_LOG_FILE[] = { "hg", "log", BASENAME, NULL };
+static const gchar *HG_CMD_LOG_DIR[] = { "hg", "log", ABS_DIRNAME, NULL };
 static const gchar *HG_CMD_COMMIT[] = { "hg", "commit", "-m", MESSAGE, FILE_LIST, NULL };
-static const gchar *HG_CMD_BLAME[] = { "hg", "annotate", BASE_FILENAME, NULL };
-static const gchar *HG_CMD_SHOW[] = { "hg", "cat", BASE_FILENAME, NULL };
+static const gchar *HG_CMD_BLAME[] = { "hg", "annotate", BASENAME, NULL };
+static const gchar *HG_CMD_SHOW[] = { "hg", "cat", BASENAME, NULL };
 
-static void *HG_COMMANDS[] = { HG_CMD_DIFF_FILE,
-	HG_CMD_DIFF_DIR,
-	HG_CMD_REVERT_FILE,
-	HG_CMD_STATUS,
-	HG_CMD_ADD,
-	HG_CMD_REMOVE,
-	HG_CMD_LOG_FILE,
-	HG_CMD_LOG_DIR,
-	HG_CMD_COMMIT,
-	HG_CMD_BLAME,
-	HG_CMD_SHOW
+static const VC_COMMAND commands[] = {
+	{
+	 .startdir = VC_COMMAND_STARTDIR_FILE,
+	 .command = HG_CMD_DIFF_FILE,
+	 .env = NULL,
+	 .function = NULL},
+	{
+	 .startdir = VC_COMMAND_STARTDIR_FILE,
+	 .command = HG_CMD_DIFF_DIR,
+	 .env = NULL,
+	 .function = NULL},
+	{
+	 .startdir = VC_COMMAND_STARTDIR_FILE,
+	 .command = HG_CMD_REVERT_FILE,
+	 .env = NULL,
+	 .function = NULL},
+	{
+	 .startdir = VC_COMMAND_STARTDIR_FILE,
+	 .command = HG_CMD_STATUS,
+	 .env = NULL,
+	 .function = NULL},
+	{
+	 .startdir = VC_COMMAND_STARTDIR_FILE,
+	 .command = HG_CMD_ADD,
+	 .env = NULL,
+	 .function = NULL},
+	{
+	 .startdir = VC_COMMAND_STARTDIR_FILE,
+	 .command = HG_CMD_REMOVE,
+	 .env = NULL,
+	 .function = NULL},
+	{
+	 .startdir = VC_COMMAND_STARTDIR_FILE,
+	 .command = HG_CMD_LOG_FILE,
+	 .env = NULL,
+	 .function = NULL},
+	{
+	 .startdir = VC_COMMAND_STARTDIR_FILE,
+	 .command = HG_CMD_LOG_DIR,
+	 .env = NULL,
+	 .function = NULL},
+	{
+	 .startdir = VC_COMMAND_STARTDIR_FILE,
+	 .command = HG_CMD_COMMIT,
+	 .env = NULL,
+	 .function = NULL},
+	{
+	 .startdir = VC_COMMAND_STARTDIR_FILE,
+	 .command = HG_CMD_BLAME,
+	 .env = NULL,
+	 .function = NULL},
+	{
+	 .startdir = VC_COMMAND_STARTDIR_FILE,
+	 .command = HG_CMD_SHOW,
+	 .env = NULL,
+	 .function = NULL}
 };
 
+static gchar *
+get_base_dir(const gchar * path)
+{
+	return find_subdir_path(path, ".hg");
+}
+
 static gboolean
 in_vc_hg(const gchar * filename)
 {
@@ -80,7 +131,7 @@
 	base_name = g_path_get_basename(filename);
 	argv[3] = base_name;
 
-	exit_code = execute_custom_command((const gchar **) argv, NULL, &std_output, NULL,
+	exit_code = execute_custom_command(dir, (const gchar **) argv, NULL, &std_output, NULL,
 					   dir, NULL, NULL);
 	if (NZV(std_output))
 	{
@@ -119,7 +170,7 @@
 
 	g_return_val_if_fail(base_dir, NULL);
 
-	execute_custom_command(argv, NULL, &txt, NULL, base_dir, NULL, NULL);
+	execute_custom_command(base_dir, argv, NULL, &txt, NULL, base_dir, NULL, NULL);
 	if (!NZV(txt))
 	{
 		g_free(base_dir);
@@ -181,4 +232,10 @@
 	return ret;
 }
 
-VC_RECORD VC_HG = { HG_COMMANDS, NO_ENV, "hg", in_vc_hg, get_commit_files_hg };
+VC_RECORD VC_HG = {
+	.commands = commands,
+	.program = "hg",
+	.get_base_dir = get_base_dir,
+	.in_vc = in_vc_hg,
+	.get_commit_files = get_commit_files_hg,
+};

Modified: trunk/geanyvc/vc_svk.c
===================================================================
--- trunk/geanyvc/vc_svk.c	2008-09-18 12:13:16 UTC (rev 178)
+++ trunk/geanyvc/vc_svk.c	2008-09-19 21:29:46 UTC (rev 179)
@@ -35,31 +35,85 @@
 extern GeanyData *geany_data;
 
 
-static const gchar *SVK_CMD_DIFF_FILE[] = { "svk", "diff", FILENAME, NULL };
-static const gchar *SVK_CMD_DIFF_DIR[] = { "svk", "diff", DIRNAME, NULL };
-static const gchar *SVK_CMD_REVERT_FILE[] = { "svk", "revert", BASE_FILENAME, NULL };
+static const gchar *SVK_CMD_DIFF_FILE[] = { "svk", "diff", ABS_FILENAME, NULL };
+static const gchar *SVK_CMD_DIFF_DIR[] = { "svk", "diff", ABS_DIRNAME, NULL };
+static const gchar *SVK_CMD_REVERT_FILE[] = { "svk", "revert", BASENAME, NULL };
 static const gchar *SVK_CMD_STATUS[] = { "svk", "status", NULL };
-static const gchar *SVK_CMD_ADD[] = { "svk", "add", BASE_FILENAME, NULL };
-static const gchar *SVK_CMD_REMOVE[] = { "svk", "remove", BASE_FILENAME, NULL };
-static const gchar *SVK_CMD_LOG_FILE[] = { "svk", "log", BASE_FILENAME, NULL };
-static const gchar *SVK_CMD_LOG_DIR[] = { "svk", "log", DIRNAME, NULL };
+static const gchar *SVK_CMD_ADD[] = { "svk", "add", BASENAME, NULL };
+static const gchar *SVK_CMD_REMOVE[] = { "svk", "remove", BASENAME, NULL };
+static const gchar *SVK_CMD_LOG_FILE[] = { "svk", "log", BASENAME, NULL };
+static const gchar *SVK_CMD_LOG_DIR[] = { "svk", "log", ABS_DIRNAME, NULL };
 static const gchar *SVK_CMD_COMMIT[] = { "svk", "commit", "-m", MESSAGE, FILE_LIST, NULL };
-static const gchar *SVK_CMD_BLAME[] = { "svk", "blame", BASE_FILENAME, NULL };
-static const gchar *SVK_CMD_SHOW[] = { "svk", "cat", BASE_FILENAME, NULL };
+static const gchar *SVK_CMD_BLAME[] = { "svk", "blame", BASENAME, NULL };
+static const gchar *SVK_CMD_SHOW[] = { "svk", "cat", BASENAME, NULL };
 
-static void *SVK_COMMANDS[] = { SVK_CMD_DIFF_FILE,
-	SVK_CMD_DIFF_DIR,
-	SVK_CMD_REVERT_FILE,
-	SVK_CMD_STATUS,
-	SVK_CMD_ADD,
-	SVK_CMD_REMOVE,
-	SVK_CMD_LOG_FILE,
-	SVK_CMD_LOG_DIR,
-	SVK_CMD_COMMIT,
-	SVK_CMD_BLAME,
-	SVK_CMD_SHOW
+
+static const VC_COMMAND commands[] = {
+	{
+	 .startdir = VC_COMMAND_STARTDIR_FILE,
+	 .command = SVK_CMD_DIFF_FILE,
+	 .env = NULL,
+	 .function = NULL},
+	{
+	 .startdir = VC_COMMAND_STARTDIR_FILE,
+	 .command = SVK_CMD_DIFF_DIR,
+	 .env = NULL,
+	 .function = NULL},
+	{
+	 .startdir = VC_COMMAND_STARTDIR_FILE,
+	 .command = SVK_CMD_REVERT_FILE,
+	 .env = NULL,
+	 .function = NULL},
+	{
+	 .startdir = VC_COMMAND_STARTDIR_FILE,
+	 .command = SVK_CMD_STATUS,
+	 .env = NULL,
+	 .function = NULL},
+	{
+	 .startdir = VC_COMMAND_STARTDIR_FILE,
+	 .command = SVK_CMD_ADD,
+	 .env = NULL,
+	 .function = NULL},
+	{
+	 .startdir = VC_COMMAND_STARTDIR_FILE,
+	 .command = SVK_CMD_REMOVE,
+	 .env = NULL,
+	 .function = NULL},
+	{
+	 .startdir = VC_COMMAND_STARTDIR_FILE,
+	 .command = SVK_CMD_LOG_FILE,
+	 .env = NULL,
+	 .function = NULL},
+	{
+	 .startdir = VC_COMMAND_STARTDIR_FILE,
+	 .command = SVK_CMD_LOG_DIR,
+	 .env = NULL,
+	 .function = NULL},
+	{
+	 .startdir = VC_COMMAND_STARTDIR_FILE,
+	 .command = SVK_CMD_COMMIT,
+	 .env = NULL,
+	 .function = NULL},
+	{
+	 .startdir = VC_COMMAND_STARTDIR_FILE,
+	 .command = SVK_CMD_BLAME,
+	 .env = NULL,
+	 .function = NULL},
+	{
+	 .startdir = VC_COMMAND_STARTDIR_FILE,
+	 .command = SVK_CMD_SHOW,
+	 .env = NULL,
+	 .function = NULL}
 };
 
+
+static gchar *
+get_base_dir(const gchar * path)
+{
+	// NOT IMPLEMENTED
+	return NULL;
+}
+
 static gboolean
 in_vc_svk(const gchar * filename)
 {
@@ -72,8 +126,9 @@
 
 	if (g_file_test(filename, G_FILE_TEST_IS_DIR))
 	{
-		exit_code = execute_custom_command((const gchar **) argv, NULL, NULL, NULL,
-						   filename, NULL, NULL);
+		exit_code =
+			execute_custom_command(filename, (const gchar **) argv, NULL, NULL, NULL,
+					       filename, NULL, NULL);
 
 	}
 	else
@@ -83,7 +138,7 @@
 
 		argv[2] = base_name;
 
-		exit_code = execute_custom_command((const gchar **) argv, NULL, NULL, NULL,
+		exit_code = execute_custom_command(dir, (const gchar **) argv, NULL, NULL, NULL,
 						   dir, NULL, NULL);
 
 		g_free(dir);
@@ -120,7 +175,7 @@
 	gchar *filename;
 	const char *argv[] = { "svk", "status", NULL };
 
-	execute_custom_command(argv, NULL, &txt, NULL, dir, NULL, NULL);
+	execute_custom_command(dir, argv, NULL, &txt, NULL, dir, NULL, NULL);
 	if (!NZV(txt))
 		return NULL;
 	p = txt;
@@ -194,5 +249,10 @@
 	return ret;
 }
 
-
-VC_RECORD VC_SVK = { SVK_COMMANDS, NO_ENV, "svk", in_vc_svk, get_commit_files_svk };
+VC_RECORD VC_SVK = {
+	.commands = commands,
+	.program = "svk",
+	.get_base_dir = get_base_dir,
+	.in_vc = in_vc_svk,
+	.get_commit_files = get_commit_files_svk,
+};

Modified: trunk/geanyvc/vc_svn.c
===================================================================
--- trunk/geanyvc/vc_svn.c	2008-09-18 12:13:16 UTC (rev 178)
+++ trunk/geanyvc/vc_svn.c	2008-09-19 21:29:46 UTC (rev 179)
@@ -35,32 +35,85 @@
 extern GeanyData *geany_data;
 
 
-static const gchar *SVN_CMD_DIFF_FILE[] = { "svn", "diff", "--non-interactive", FILENAME, NULL };
-static const gchar *SVN_CMD_DIFF_DIR[] = { "svn", "diff", "--non-interactive", DIRNAME, NULL };
-static const gchar *SVN_CMD_REVERT_FILE[] = { "svn", "revert", BASE_FILENAME, NULL };
+static const gchar *SVN_CMD_DIFF_FILE[] =
+	{ "svn", "diff", "--non-interactive", BASE_FILENAME, NULL };
+static const gchar *SVN_CMD_DIFF_DIR[] = { "svn", "diff", "--non-interactive", BASE_DIRNAME, NULL };
+static const gchar *SVN_CMD_REVERT_FILE[] = { "svn", "revert", BASENAME, NULL };
 static const gchar *SVN_CMD_STATUS[] = { "svn", "status", NULL };
-static const gchar *SVN_CMD_ADD[] = { "svn", "add", BASE_FILENAME, NULL };
-static const gchar *SVN_CMD_REMOVE[] = { "svn", "rm", BASE_FILENAME, NULL };
-static const gchar *SVN_CMD_LOG_FILE[] = { "svn", "log", BASE_FILENAME, NULL };
-static const gchar *SVN_CMD_LOG_DIR[] = { "svn", "log", DIRNAME, NULL };
+static const gchar *SVN_CMD_ADD[] = { "svn", "add", BASENAME, NULL };
+static const gchar *SVN_CMD_REMOVE[] = { "svn", "rm", BASENAME, NULL };
+static const gchar *SVN_CMD_LOG_FILE[] = { "svn", "log", BASENAME, NULL };
+static const gchar *SVN_CMD_LOG_DIR[] = { "svn", "log", ABS_DIRNAME, NULL };
 static const gchar *SVN_CMD_COMMIT[] =
 	{ "svn", "commit", "--non-interactive", "-m", MESSAGE, FILE_LIST, NULL };
-static const gchar *SVN_CMD_BLAME[] = { "svn", "blame", BASE_FILENAME, NULL };
-static const gchar *SVN_CMD_SHOW[] = { "svn", "cat", BASE_FILENAME, NULL };
+static const gchar *SVN_CMD_BLAME[] = { "svn", "blame", BASENAME, NULL };
+static const gchar *SVN_CMD_SHOW[] = { "svn", "cat", BASENAME, NULL };
 
-static void *SVN_COMMANDS[] = { SVN_CMD_DIFF_FILE,
-	SVN_CMD_DIFF_DIR,
-	SVN_CMD_REVERT_FILE,
-	SVN_CMD_STATUS,
-	SVN_CMD_ADD,
-	SVN_CMD_REMOVE,
-	SVN_CMD_LOG_FILE,
-	SVN_CMD_LOG_DIR,
-	SVN_CMD_COMMIT,
-	SVN_CMD_BLAME,
-	SVN_CMD_SHOW
+static const VC_COMMAND commands[] = {
+	{
+	 .startdir = VC_COMMAND_STARTDIR_BASE,
+	 .command = SVN_CMD_DIFF_FILE,
+	 .env = NULL,
+	 .function = NULL},
+	{
+	 .startdir = VC_COMMAND_STARTDIR_BASE,
+	 .command = SVN_CMD_DIFF_DIR,
+	 .env = NULL,
+	 .function = NULL},
+	{
+	 .startdir = VC_COMMAND_STARTDIR_FILE,
+	 .command = SVN_CMD_REVERT_FILE,
+	 .env = NULL,
+	 .function = NULL},
+	{
+	 .startdir = VC_COMMAND_STARTDIR_FILE,
+	 .command = SVN_CMD_STATUS,
+	 .env = NULL,
+	 .function = NULL},
+	{
+	 .startdir = VC_COMMAND_STARTDIR_FILE,
+	 .command = SVN_CMD_ADD,
+	 .env = NULL,
+	 .function = NULL},
+	{
+	 .startdir = VC_COMMAND_STARTDIR_FILE,
+	 .command = SVN_CMD_REMOVE,
+	 .env = NULL,
+	 .function = NULL},
+	{
+	 .startdir = VC_COMMAND_STARTDIR_FILE,
+	 .command = SVN_CMD_LOG_FILE,
+	 .env = NULL,
+	 .function = NULL},
+	{
+	 .startdir = VC_COMMAND_STARTDIR_FILE,
+	 .command = SVN_CMD_LOG_DIR,
+	 .env = NULL,
+	 .function = NULL},
+	{
+	 .startdir = VC_COMMAND_STARTDIR_FILE,
+	 .command = SVN_CMD_COMMIT,
+	 .env = NULL,
+	 .function = NULL},
+	{
+	 .startdir = VC_COMMAND_STARTDIR_FILE,
+	 .command = SVN_CMD_BLAME,
+	 .env = NULL,
+	 .function = NULL},
+	{
+	 .startdir = VC_COMMAND_STARTDIR_FILE,
+	 .command = SVN_CMD_SHOW,
+	 .env = NULL,
+	 .function = NULL}
 };
 
+static gchar *
+get_base_dir(const gchar * path)
+{
+	// NOT IMPLEMENTED
+	return find_subdir_path(path, ".svn");
+}
+
 static gboolean
 in_vc_svn(const gchar * filename)
 {
@@ -81,7 +134,7 @@
 	base_name = g_path_get_basename(filename);
 	argv[3] = base_name;
 
-	exit_code = execute_custom_command((const gchar **) argv, NULL, &std_output, NULL,
+	exit_code = execute_custom_command(dir, (const gchar **) argv, NULL, &std_output, NULL,
 					   dir, NULL, NULL);
 	if (NZV(std_output))
 	{
@@ -116,7 +169,7 @@
 	gchar *filename;
 	const char *argv[] = { "svn", "status", NULL };
 
-	execute_custom_command(argv, NULL, &txt, NULL, dir, NULL, NULL);
+	execute_custom_command(dir, argv, NULL, &txt, NULL, dir, NULL, NULL);
 	if (!NZV(txt))
 		return NULL;
 	p = txt;
@@ -190,4 +243,10 @@
 	return ret;
 }
 
-VC_RECORD VC_SVN = { SVN_COMMANDS, NO_ENV, "svn", in_vc_svn, get_commit_files_svn };
+VC_RECORD VC_SVN = {
+	.commands = commands,
+	.program = "svn",
+	.get_base_dir = get_base_dir,
+	.in_vc = in_vc_svn,
+	.get_commit_files = get_commit_files_svn,
+};


This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.



More information about the Plugins-Commits mailing list