[geany/geany-plugins] 88ca17: Merge pull request #969 from nomadbyte/fossil-scm

Frank Lanitz git-noreply at xxxxx
Mon May 11 17:52:52 UTC 2020


Branch:      refs/heads/master
Author:      Frank Lanitz <frank at frank.uvena.de>
Committer:   GitHub <noreply at github.com>
Date:        Mon, 11 May 2020 17:52:52 UTC
Commit:      88ca170758d1754048c9796618cccfc16b8e464c
             https://github.com/geany/geany-plugins/commit/88ca170758d1754048c9796618cccfc16b8e464c

Log Message:
-----------
Merge pull request #969 from nomadbyte/fossil-scm

GeanyVC: Add support for Fossil SCM (fossil-scm.org)


Modified Paths:
--------------
    geanyvc/README
    geanyvc/src/Makefile.am
    geanyvc/src/geanyvc.c
    geanyvc/src/unittests.c
    geanyvc/src/vc_fossil.c
    po/POTFILES.in
    po/be.po
    po/ca.po
    po/da.po
    po/de.po
    po/el.po
    po/es.po
    po/fr.po
    po/gl.po
    po/it.po
    po/ja.po
    po/kk.po
    po/nl.po
    po/pt.po
    po/pt_BR.po
    po/ru.po
    po/tr.po
    po/zh_CN.po

Modified: geanyvc/README
8 lines changed, 4 insertions(+), 4 deletions(-)
===================================================================
@@ -14,8 +14,8 @@ revert and commit most time.
 Features
 --------
 
-*Bazaar, GIT, Mercurial, Subversion, SVK*
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+*Bazaar, Fossil, GIT, Mercurial, Subversion, SVK*
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 * diff file
 * diff directory
@@ -96,8 +96,8 @@ If this option is activated and you have **meld**, **kompare**,
 one of these program will be used to show differences for "Diff From
 Current File" command.
 
-*Enable CVS/GIT/SVN/SVK/Bazaar/Mercurial*
-+++++++++++++++++++++++++++++++++++++++++
+*Enable CVS/GIT/SVN/SVK/Bazaar/Fossil/Mercurial*
+++++++++++++++++++++++++++++++++++++++++++++++++
 
 GeanyVC detects if opened file is in version control by checking
 directories and executing commands from version control systems


Modified: geanyvc/src/Makefile.am
5 lines changed, 3 insertions(+), 2 deletions(-)
===================================================================
@@ -9,6 +9,7 @@ geanyvc_la_SOURCES = \
 	utils.c \
 	vc_bzr.c \
 	vc_cvs.c \
+	vc_fossil.c \
 	vc_git.c \
 	vc_hg.c \
 	vc_svk.c \
@@ -27,8 +28,8 @@ geanyvc_la_LIBADD = \
 if UNITTESTS
 TESTS = unittests
 check_PROGRAMS = unittests
-unittests_SOURCES = unittests.c utils.c
-unittests_CFLAGS  = $(GEANY_CFLAGS) -DUNITTESTS
+unittests_SOURCES = unittests.c $(geanyvc_la_SOURCES)
+unittests_CFLAGS  = $(GEANY_CFLAGS) $(geanyvc_la_CFLAGS) -DUNITTESTS
 unittests_LDADD   = @GEANY_LIBS@ $(INTLLIBS) @CHECK_LIBS@
 endif
 


Modified: geanyvc/src/geanyvc.c
14 lines changed, 13 insertions(+), 1 deletions(-)
===================================================================
@@ -22,7 +22,7 @@
  */
 
 /* VC plugin */
-/* This plugin allow to works with cvs/svn/git inside geany light IDE. */
+/* This plugin allows to work with cvs/svn/git/bzr/fossil inside geany light IDE. */
 
 #include <string.h>
 #include <glib.h>
@@ -90,6 +90,7 @@ static gchar *config_file;
 
 static gboolean enable_cvs;
 static gboolean enable_git;
+static gboolean enable_fossil;
 static gboolean enable_svn;
 static gboolean enable_svk;
 static gboolean enable_bzr;
@@ -1908,6 +1909,7 @@ static struct
 	GtkWidget *cb_attach_to_menubar;
 	GtkWidget *cb_cvs;
 	GtkWidget *cb_git;
+	GtkWidget *cb_fossil;
 	GtkWidget *cb_svn;
 	GtkWidget *cb_svk;
 	GtkWidget *cb_bzr;
@@ -1938,6 +1940,7 @@ save_config(void)
 
 	g_key_file_set_boolean(config, "VC", "enable_cvs", enable_cvs);
 	g_key_file_set_boolean(config, "VC", "enable_git", enable_git);
+	g_key_file_set_boolean(config, "VC", "enable_fossil", enable_fossil);
 	g_key_file_set_boolean(config, "VC", "enable_svn", enable_svn);
 	g_key_file_set_boolean(config, "VC", "enable_svk", enable_svk);
 	g_key_file_set_boolean(config, "VC", "enable_bzr", enable_bzr);
@@ -2007,6 +2010,7 @@ on_configure_response(G_GNUC_UNUSED GtkDialog * dialog, gint response,
 
 		enable_cvs = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widgets.cb_cvs));
 		enable_git = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widgets.cb_git));
+		enable_fossil = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widgets.cb_fossil));
 		enable_svn = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widgets.cb_svn));
 		enable_svk = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widgets.cb_svk));
 		enable_bzr = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widgets.cb_bzr));
@@ -2103,6 +2107,11 @@ plugin_configure(GtkDialog * dialog)
 	gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widgets.cb_git), enable_git);
 	gtk_box_pack_start(GTK_BOX(vbox), widgets.cb_git, TRUE, FALSE, 2);
 
+	widgets.cb_fossil = gtk_check_button_new_with_label(_("Enable Fossil"));
+	gtk_button_set_focus_on_click(GTK_BUTTON(widgets.cb_fossil), FALSE);
+	gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widgets.cb_fossil), enable_fossil);
+	gtk_box_pack_start(GTK_BOX(vbox), widgets.cb_fossil, TRUE, FALSE, 2);
+
 	widgets.cb_svn = gtk_check_button_new_with_label(_("Enable SVN"));
 	gtk_button_set_focus_on_click(GTK_BUTTON(widgets.cb_svn), FALSE);
 	gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widgets.cb_svn), enable_svn);
@@ -2167,6 +2176,8 @@ load_config(void)
 		TRUE);
 	enable_git = utils_get_setting_boolean(config, "VC", "enable_git",
 		TRUE);
+	enable_fossil = utils_get_setting_boolean(config, "VC", "enable_fossil",
+		TRUE);
 	enable_svn = utils_get_setting_boolean(config, "VC", "enable_svn",
 		TRUE);
 	enable_svk = utils_get_setting_boolean(config, "VC", "enable_svk",
@@ -2218,6 +2229,7 @@ registrate(void)
 		g_slist_free(VC);
 		VC = NULL;
 	}
+	REGISTER_VC(FOSSIL, enable_fossil);
 	REGISTER_VC(GIT, enable_git);
 	REGISTER_VC(SVN, enable_svn);
 	REGISTER_VC(CVS, enable_cvs);


Modified: geanyvc/src/unittests.c
3 lines changed, 3 insertions(+), 0 deletions(-)
===================================================================
@@ -7,13 +7,16 @@
 #include "geany.h"
 
 extern TCase *utils_test_case_create(void);
+extern TCase *vc_fossil_test_case_create(void);
 
 Suite *
 my_suite(void)
 {
 	Suite *s = suite_create("VC");
 	TCase *tc_utils = utils_test_case_create();
+	TCase *tc_vc_fossil = vc_fossil_test_case_create();
 	suite_add_tcase(s, tc_utils);
+	suite_add_tcase(s, tc_vc_fossil);
 	return s;
 }
 


Modified: geanyvc/src/vc_fossil.c
590 lines changed, 590 insertions(+), 0 deletions(-)
===================================================================
@@ -0,0 +1,590 @@
+/*
+ *      Copyright 2020 Artur Shepilko <nomadbyte at gmail.com>
+ *      Copyright 2007-2011 Frank Lanitz <frank(at)frank(dot)uvena(dot)de>
+ *      Copyright 2007-2009 Enrico Tröger <enrico.troeger at uvena.de>
+ *      Copyright 2007 Nick Treleaven <nick.treleaven at btinternet.com>
+ *      Copyright 2007-2009 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, write to the Free Software
+ *      Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include <string.h>
+#include <geanyplugin.h>
+#include "geanyvc.h"
+
+extern GeanyData *geany_data;
+
+#define FOSSIL_CLIENT "fossil"
+#define FOSSIL_CMD_LOG_WIDTH "0"  /* 0:single-line */
+#define FOSSIL_CMD_LOG_NUM   "300"
+
+static const gchar *FOSSIL_CMD_DIFF_FILE[] = { FOSSIL_CLIENT, "diff", BASENAME, NULL };
+static const gchar *FOSSIL_CMD_DIFF_DIR[] = { FOSSIL_CLIENT, "diff", BASE_DIRNAME, NULL };
+static const gchar *FOSSIL_CMD_REVERT_FILE[] = { FOSSIL_CLIENT, "revert", BASENAME, NULL };
+static const gchar *FOSSIL_CMD_REVERT_DIR[] = { FOSSIL_CLIENT, "revert", BASE_DIRNAME, NULL };
+static const gchar *FOSSIL_CMD_STATUS[] = { FOSSIL_CLIENT, "status", NULL };
+static const gchar *FOSSIL_CMD_ADD[] = { FOSSIL_CLIENT, "add", BASENAME, NULL };
+static const gchar *FOSSIL_CMD_REMOVE[] = { FOSSIL_CLIENT, "delete", BASENAME, NULL };
+static const gchar *FOSSIL_CMD_LOG_FILE[] =
+	{ FOSSIL_CLIENT, "timeline", "ancestors", "current", "--path", BASENAME,
+		"-W", FOSSIL_CMD_LOG_WIDTH, "-n", FOSSIL_CMD_LOG_NUM, NULL };
+static const gchar *FOSSIL_CMD_LOG_DIR[] =
+	{ FOSSIL_CLIENT, "timeline", "ancestors", "current", "--path", BASE_DIRNAME,
+		"-W", FOSSIL_CMD_LOG_WIDTH, "-n", FOSSIL_CMD_LOG_NUM, NULL };
+static const gchar *FOSSIL_CMD_COMMIT[] =
+	{ FOSSIL_CLIENT, "commit", "-m", MESSAGE, FILE_LIST, NULL };
+static const gchar *FOSSIL_CMD_BLAME[] = { FOSSIL_CLIENT, "blame", BASENAME, NULL };
+static const gchar *FOSSIL_CMD_UPDATE[] ={ FOSSIL_CLIENT, "update", NULL };
+static const gchar *FOSSIL_CMD_SHOW[] = { FOSSIL_CLIENT, "cat", BASENAME, NULL };
+
+static gchar *
+parse_fossil_info(const gchar * txt, const gchar * fld)
+{
+	gchar *val = NULL;
+	gchar *start, *end;
+	gint len;
+
+	start = strstr(txt, fld);
+	g_return_val_if_fail(start, NULL);
+	if (!start) return NULL;
+
+	start += strlen(fld);
+	while (*start == ' ' || *start == '\t') ++start;
+
+	end = strchr(start, '\n');
+	len = ( end ? end - start : strlen(start) );
+
+	if (strcmp(fld, "local-root:") == 0)
+	{
+		if (!len) return NULL;
+	}
+	else if (strcmp(fld, "checkout:") == 0
+		     || strcmp(fld, "parent:") == 0)
+	{
+		/* extract id from string:
+		 * "id date"
+		 */
+		end = strstr(start, " ");
+		if (!end) return NULL;
+
+		for (--end; *end == ' ' || *end == '\t'; --end) {}
+		len = end - start + 1;
+	}
+	else if (strcmp(fld, "comment:") == 0)
+	{
+		/* extract comment text from string:
+		 * "comment text (user: username)"
+		 */
+		end = g_strrstr(start, "(user:");
+		if (!end) return NULL;
+
+		for (--end; *end == ' ' || *end == '\t'; --end) {}
+		len = end - start + 1;
+	}
+	else if (strcmp(fld, "user:") == 0)
+	{
+		/* extract username from string:
+		 * "username)"
+		 */
+		end = g_strrstr(start, ")");
+		if (!end) return NULL;
+
+		--end;
+		len = end - start + 1;
+	}
+
+	val = g_malloc0(len + 1);
+	memcpy(val, start, len);
+
+	return val;
+}
+
+static gchar *
+get_base_dir(const gchar * path)
+{
+	gchar *base_dir = NULL;
+	const gchar *argv[] = { FOSSIL_CLIENT, "info", NULL };
+	gchar *dir = NULL;
+	gchar *filename = NULL;
+	gchar *std_out = NULL;
+	gchar *std_err = NULL;
+
+	if (g_file_test(path, G_FILE_TEST_IS_DIR))
+		dir = g_strdup(path);
+	else
+		dir = g_path_get_dirname(path);
+
+	execute_custom_command(dir, (const gchar **) argv, NULL, &std_out, &std_err,
+			       dir, NULL, NULL);
+    g_free(dir);
+    if (!std_out) return NULL;
+
+    dir = parse_fossil_info(std_out, "local-root:");
+	g_free(std_out);
+	if (!dir) return NULL;
+
+	filename = g_build_filename(dir, ".", NULL); /* in case of a trailing slash */
+	base_dir = g_path_get_dirname(filename);
+
+	g_free(filename);
+	g_free(dir);
+
+	return base_dir;
+}
+
+static gboolean
+in_vc_fossil(const gchar * filename)
+{
+	const gchar *argv[] = { FOSSIL_CLIENT, "ls", NULL, NULL };
+	gchar *dir;
+	gchar *base_name;
+	gboolean ret = FALSE;
+	gchar *std_out;
+	gchar *std_err;
+
+	if (g_file_test(filename, G_FILE_TEST_IS_DIR))
+	{
+		gchar *base_dir = get_base_dir(filename);
+
+		if (!base_dir) return FALSE;
+
+		g_free(base_dir);
+		return TRUE;
+	}
+
+	dir = g_path_get_dirname(filename);
+	base_name = g_path_get_basename(filename);
+	argv[2] = base_name;
+
+	execute_custom_command(dir, (const gchar **) argv, NULL, &std_out, &std_err,
+			       dir, NULL, NULL);
+
+	if (!EMPTY(std_out))
+	{
+		ret = TRUE;
+		g_free(std_out);
+	}
+
+	g_free(base_name);
+	g_free(dir);
+
+	return ret;
+}
+
+static GSList *
+parse_fossil_status(GSList * lst, const gchar * base_dir, const gchar * txt, const gchar * s_out,
+		 const gchar * status)
+{
+	gchar *start, *end;
+	gchar *base_name;
+	gchar *filename;
+	gboolean got_error = FALSE;
+
+	for (start = strstr(txt, s_out); start; start = strstr(start, s_out))
+	{
+		gint len = 0;
+		CommitItem *item;
+
+		start += strlen(s_out);
+		end = strchr(start, '\n');
+		got_error = (!end);
+		if (got_error) break;
+
+		start = strchr(start,' '); /* allow partial match; jump to separator  */
+		got_error = (!start || start > end);
+		if (got_error) break;
+
+		while (*start == ' ' || *start == '\t') ++start;
+		got_error = (!*start);
+		if (got_error) break;
+
+		len = end - start;
+		base_name = g_malloc0(len + 1);
+		memcpy(base_name, start, len);
+		filename = g_build_filename(base_dir, base_name, NULL);
+		g_free(base_name);
+
+		item = g_new(CommitItem, 1);
+		item->status = status;
+		item->path = filename;
+
+		lst = g_slist_append(lst, item);
+	}
+
+	if (got_error)
+	{
+		GSList *e;
+		for (e = lst; e ; e = g_slist_next(e))
+		{
+			CommitItem *item = (CommitItem *) (e->data);
+			g_free(item->path);
+			g_free(item);
+		}
+		g_slist_free(lst);
+		lst = NULL;
+	}
+
+	return lst;
+}
+
+static GSList *
+get_commit_files_fossil(const gchar * file)
+{
+	const gchar *argv[] = { FOSSIL_CLIENT, "status", NULL };
+	gchar *std_out = NULL;
+	gchar *base_dir = get_base_dir(file);
+	GSList *ret = NULL;
+
+	g_return_val_if_fail(base_dir, NULL);
+	if (!base_dir) return NULL;
+
+	execute_custom_command(base_dir, (const gchar **) argv, (const gchar **) NULL,
+			       &std_out, NULL, base_dir, NULL, NULL);
+	g_return_val_if_fail(std_out, NULL);
+
+
+	ret = parse_fossil_status(ret, base_dir, std_out, "EDITED", FILE_STATUS_MODIFIED);
+	ret = parse_fossil_status(ret, base_dir, std_out, "UPDATED", FILE_STATUS_MODIFIED);
+	ret = parse_fossil_status(ret, base_dir, std_out, "ADDED", FILE_STATUS_ADDED);
+	ret = parse_fossil_status(ret, base_dir, std_out, "DELETED", FILE_STATUS_DELETED);
+
+	g_free(std_out);
+	g_free(base_dir);
+
+	return ret;
+}
+
+static gint
+fossil_revert_dir(gchar ** std_out, gchar ** std_err, const gchar * path,
+	 GSList * list, const gchar * message)
+{
+	gchar *base_dir = get_base_dir(path);
+    const char **argv = (const gchar **)FOSSIL_CMD_REVERT_DIR;
+	const gchar *base_argv[] = { FOSSIL_CLIENT, "revert", NULL, NULL };
+	gint ret;
+
+	g_return_val_if_fail(base_dir, -1);
+	if (!base_dir) return -1;
+
+	if ( g_strcmp0(path, base_dir) == 0 )
+		argv = (const gchar **)base_argv;
+
+	ret = execute_custom_command(base_dir, argv, (const gchar **) NULL,
+						std_out, std_err, path, list, message);
+	g_free(base_dir);
+	return ret;
+}
+
+static gint
+fossil_status_extra(gchar ** std_out, gchar ** std_err, const gchar * path,
+	 GSList * list, const gchar * message)
+{
+	gchar *base_dir = get_base_dir(path);
+	gint ret = 0;
+
+	g_return_val_if_fail(base_dir, -1);
+	if (!base_dir) return -1;
+
+	ret = execute_custom_command(base_dir, FOSSIL_CMD_STATUS, (const gchar **) NULL,
+						std_out, std_err, path, list, message);
+
+	if (ret)
+	{
+		g_free(base_dir);
+		return ret;
+	}
+
+	if (!ret)
+	{
+		const gchar *argv[] = { FOSSIL_CLIENT, "changes", "--extra", "--classify", NULL };
+		gchar *std_out1 = NULL;
+		gchar *std_err1 = NULL;
+
+		if (std_out)
+		{
+			std_out1 = *std_out;
+			*std_out = NULL;
+		}
+		if (std_err)
+		{
+			std_err1 = *std_err;
+			*std_err = NULL;
+		}
+
+		ret = execute_custom_command(base_dir, (const gchar **) argv, (const gchar **) NULL,
+							std_out, std_err, path, list, message);
+
+		if (std_out1)
+		{
+			*std_out = g_strconcat(std_out1, *std_out, NULL);
+			g_free(std_out1);
+		}
+		if (std_err1)
+		{
+			*std_err = g_strconcat(std_err1, *std_err, NULL);
+			g_free(std_err1);
+		}
+	}
+
+	g_free(base_dir);
+	return ret;
+}
+
+static const VC_COMMAND commands[VC_COMMAND_COUNT] = {
+	{
+		VC_COMMAND_STARTDIR_FILE,
+		FOSSIL_CMD_DIFF_FILE,
+		NULL,
+		NULL},
+	{
+		VC_COMMAND_STARTDIR_FILE,
+		FOSSIL_CMD_DIFF_DIR,
+		NULL,
+		NULL},
+	{
+		VC_COMMAND_STARTDIR_FILE,
+		FOSSIL_CMD_REVERT_FILE,
+		NULL,
+		NULL},
+	{
+		VC_COMMAND_STARTDIR_BASE,
+		NULL,
+		NULL,
+		fossil_revert_dir},
+	{
+		VC_COMMAND_STARTDIR_FILE,
+		NULL,
+		NULL,
+		fossil_status_extra},
+	{
+		VC_COMMAND_STARTDIR_FILE,
+		FOSSIL_CMD_ADD,
+		NULL,
+		NULL},
+	{
+		VC_COMMAND_STARTDIR_FILE,
+		FOSSIL_CMD_REMOVE,
+		NULL,
+		NULL},
+	{
+		VC_COMMAND_STARTDIR_FILE,
+		FOSSIL_CMD_LOG_FILE,
+		NULL,
+		NULL},
+	{
+		VC_COMMAND_STARTDIR_FILE,
+		FOSSIL_CMD_LOG_DIR,
+		NULL,
+		NULL},
+	{
+		VC_COMMAND_STARTDIR_FILE,
+		FOSSIL_CMD_COMMIT,
+		NULL,
+		NULL},
+	{
+		VC_COMMAND_STARTDIR_FILE,
+		FOSSIL_CMD_BLAME,
+		NULL,
+		NULL},
+	{
+		VC_COMMAND_STARTDIR_FILE,
+		FOSSIL_CMD_SHOW,
+		NULL,
+		NULL},
+	{
+		VC_COMMAND_STARTDIR_BASE,
+		FOSSIL_CMD_UPDATE,
+		NULL,
+		NULL}
+};
+
+VC_RECORD VC_FOSSIL = {
+	commands,
+	FOSSIL_CLIENT,
+	get_base_dir,
+	in_vc_fossil,
+	get_commit_files_fossil,
+};
+
+
+#ifdef UNITTESTS
+#include <check.h>
+
+START_TEST(test_parse_fossil_info)
+{
+	const char *txt =
+"\
+project-name: Test\n\
+repository:   /home/developer/project/../project.fossil\n\
+local-root:   /home/developer/project/\n\
+config-db:    /home/developer/.fossil\n\
+project-code: f9e47309491679be1a7f37f11d9af42411c5bc5e\n\
+checkout:     e84c78d8eef3f7eb9b868a5766971ef8bc8d26ed 2020-03-21 02:42:21 UTC\n\
+parent:       1667f964039e1e41f06768c4721abadd704bc19c 2020-03-20 17:08:38 UTC\n\
+tags:         trunk\n\
+comment:      Test changes (user: developer)\n\
+check-ins:    10\n\
+";
+	gchar *val;
+
+	val = parse_fossil_info(txt, "unsupported-field:");
+	fail_unless(val == NULL,
+		"expected: unsupported-field: NULL, got: \"%s\"\n", val);
+	g_free(val);
+
+	val = parse_fossil_info(txt, "local-root:");
+	fail_unless(g_strcmp0(val, "/home/developer/project/") == 0,
+		"expected: local-root: \"/home/developer/project/\", got: \"%s\"\n", val);
+	g_free(val);
+
+	val = parse_fossil_info(txt, "checkout:");
+	fail_unless(g_strcmp0(val, "e84c78d8eef3f7eb9b868a5766971ef8bc8d26ed") == 0,
+		"expected: checkout: \"e84c78d8eef3f7eb9b868a5766971ef8bc8d26ed\", got: \"%s\"\n", val);
+	g_free(val);
+
+	val = parse_fossil_info(txt, "comment:");
+	fail_unless(g_strcmp0(val, "Test changes") == 0,
+		"expected: comment: \"Test changes\", got: \"%s\"\n", val);
+	g_free(val);
+
+	val = parse_fossil_info(txt, "user:");
+	fail_unless(g_strcmp0(val, "developer") == 0,
+		"expected: user: \"developer\", got: \"%s\"\n", val);
+	g_free(val);
+}
+
+END_TEST;
+
+START_TEST(test_parse_fossil_status)
+{
+	const char *txt =
+"\
+repository:   /home/developer/project/../project.fossil\n\
+local-root:   /home/developer/project/\n\
+config-db:    /home/developer/.fossil\n\
+checkout:     e84c78d8eef3f7eb9b868a5766971ef8bc8d26ed 2020-03-21 02:42:21 UTC\n\
+parent:       1667f964039e1e41f06768c4721abadd704bc19c 2020-03-20 17:08:38 UTC\n\
+tags:         trunk\n\
+comment:      Test changes (user: developer)\n\
+ADDED      added.txt\n\
+EDITED     edited1.txt\n\
+EDITED     edited2.txt\n\
+DELETED    deleted.txt\n\
+UPDATED_BY_MERGE     updated.txt\n\
+";
+	GSList *list = NULL;
+	const gchar *base_dir = "/home/developer/project";
+	CommitItem *item = NULL;
+
+ 	list = parse_fossil_status(list, base_dir, txt, "status-unsupported", FILE_STATUS_UNKNOWN);
+	fail_unless(list == NULL,
+		"expected: status-unsupported-list: NULL, got: \"%p\"\n", list);
+	g_slist_free(list);
+
+
+    /* ADDED */
+ 	list = parse_fossil_status(list, base_dir, txt, "ADDED", FILE_STATUS_ADDED);
+	fail_unless(list && list->data,
+		"expected: ADDED-list: not-NULL, got: \"%p\"\n", list);
+	fail_unless(g_slist_length(list) == 1,
+		"expected: ADDED-list: size:1, got: %d\n", g_slist_length(list));
+
+	item = (CommitItem *) (list->data);
+	fail_unless(g_strcmp0(item->path, "/home/developer/project" "/" "added.txt") == 0
+				&& item->status == FILE_STATUS_ADDED,
+		"expected: ADDED-list: item[0]: {\"%s\", %d}, got: {\"%s\", %d}\n",
+		"/home/developer/project" "/" "added.txt", FILE_STATUS_ADDED,
+		item->path, item->status);
+	g_free(item->path);
+	g_free(item);
+	g_slist_free(list);
+
+
+    /* EDITED */
+ 	list = NULL;
+ 	list = parse_fossil_status(list, base_dir, txt, "EDITED", FILE_STATUS_MODIFIED);
+	fail_unless(g_slist_length(list) == 2,
+		"expected: EDITED-list: size:2, got: %d\n", g_slist_length(list));
+
+	item = (CommitItem *) (list->data);
+	fail_unless(g_strcmp0(item->path, "/home/developer/project" "/" "edited1.txt") == 0
+				&& item->status == FILE_STATUS_MODIFIED,
+		"expected: EDITED-list: item[0]: {\"%s\", %d}, got: {\"%s\", %d}\n",
+		"/home/developer/project" "/" "edited1.txt", FILE_STATUS_MODIFIED,
+		item->path, item->status);
+	g_free(item->path);
+	g_free(item);
+
+	item = (CommitItem *) (g_slist_next(list)->data);
+	fail_unless(g_strcmp0(item->path, "/home/developer/project" "/" "edited2.txt") == 0
+				&& item->status == FILE_STATUS_MODIFIED,
+		"expected: EDITED-list: item[1]: {\"%s\", %d}, got: {\"%s\", %d}\n",
+		"/home/developer/project" "/" "edited2.txt", FILE_STATUS_MODIFIED,
+		item->path, item->status);
+	g_free(item->path);
+	g_free(item);
+	g_slist_free(list);
+
+
+    /* UPDATED, partial match */
+	list = NULL;
+ 	list = parse_fossil_status(list, base_dir, txt, "UPDATED", FILE_STATUS_MODIFIED);
+	fail_unless(list && list->data,
+		"expected: UPDATED-list: not-NULL, got: \"%p\"\n", list);
+	fail_unless(g_slist_length(list) == 1,
+		"expected: UPDATED-list: size:1, got: %d\n", g_slist_length(list));
+
+	item = (CommitItem *) (list->data);
+	fail_unless(g_strcmp0(item->path, "/home/developer/project" "/" "updated.txt") == 0
+				&& item->status == FILE_STATUS_MODIFIED,
+		"expected: UPDATED-list: item[0]: {\"%s\", %d}, got: {\"%s\", %d}\n",
+		"/home/developer/project" "/" "updated.txt", FILE_STATUS_MODIFIED,
+		item->path, item->status);
+	g_free(item->path);
+	g_free(item);
+	g_slist_free(list);
+
+
+    /* DELETED */
+	list = NULL;
+ 	list = parse_fossil_status(list, base_dir, txt, "DELETED", FILE_STATUS_DELETED);
+	fail_unless(g_slist_length(list) == 1,
+		"expected: DELETED-list: size:1, got: %d\n", g_slist_length(list));
+
+	item = (CommitItem *) (list->data);
+	fail_unless(g_strcmp0(item->path, "/home/developer/project" "/" "deleted.txt") == 0
+				&& item->status == FILE_STATUS_DELETED,
+		"expected: DELETED-list: item[0]: {\"%s\", %d}, got: {\"%s\", %d}\n",
+		"/home/developer/project" "/" "deleted.txt", FILE_STATUS_DELETED,
+		item->path, item->status);
+	g_free(item->path);
+	g_free(item);
+	g_slist_free(list);
+}
+
+END_TEST;
+
+
+TCase *
+vc_fossil_test_case_create(void)
+{
+	TCase *tc_vc_fossil = tcase_create("vc_fossil");
+	tcase_add_test(tc_vc_fossil, test_parse_fossil_info);
+	tcase_add_test(tc_vc_fossil, test_parse_fossil_status);
+	return tc_vc_fossil;
+}
+
+
+#endif


Modified: po/POTFILES.in
1 lines changed, 1 insertions(+), 0 deletions(-)
===================================================================
@@ -202,6 +202,7 @@ geanyvc/src/geanyvc.c
 geanyvc/src/geanyvc.h
 geanyvc/src/vc_bzr.c
 geanyvc/src/vc_cvs.c
+geanyvc/src/vc_fossil.c
 geanyvc/src/vc_git.c
 geanyvc/src/vc_hg.c
 geanyvc/src/vc_svk.c


Modified: po/be.po
4 lines changed, 4 insertions(+), 0 deletions(-)
===================================================================
@@ -4610,6 +4610,10 @@ msgstr ""
 msgid "Enable GIT"
 msgstr ""
 
+#: ../geanyvc/src/geanyvc.c:2110
+msgid "Enable Fossil"
+msgstr ""
+
 #: ../geanyvc/src/geanyvc.c:2106
 msgid "Enable SVN"
 msgstr ""


Modified: po/ca.po
4 lines changed, 4 insertions(+), 0 deletions(-)
===================================================================
@@ -4539,6 +4539,10 @@ msgstr "Activa CVS"
 msgid "Enable GIT"
 msgstr "Activa GIT"
 
+#: ../geanyvc/src/geanyvc.c:2110
+msgid "Enable Fossil"
+msgstr "Activa Fossil"
+
 #: ../geanyvc/src/geanyvc.c:2106
 msgid "Enable SVN"
 msgstr "Activa SVN"


Modified: po/da.po
4 lines changed, 4 insertions(+), 0 deletions(-)
===================================================================
@@ -4548,6 +4548,10 @@ msgstr ""
 msgid "Enable GIT"
 msgstr ""
 
+#: ../geanyvc/src/geanyvc.c:2110
+msgid "Enable Fossil"
+msgstr ""
+
 #: ../geanyvc/src/geanyvc.c:2106
 msgid "Enable SVN"
 msgstr ""


Modified: po/de.po
4 lines changed, 4 insertions(+), 0 deletions(-)
===================================================================
@@ -4866,6 +4866,10 @@ msgstr "CVS aktivieren"
 msgid "Enable GIT"
 msgstr "GIT aktivieren"
 
+#: ../geanyvc/src/geanyvc.c:2110
+msgid "Enable Fossil"
+msgstr "Fossil aktivieren"
+
 #: ../geanyvc/src/geanyvc.c:2106
 msgid "Enable SVN"
 msgstr "SVN aktivieren"


Modified: po/el.po
4 lines changed, 4 insertions(+), 0 deletions(-)
===================================================================
@@ -4510,6 +4510,10 @@ msgstr ""
 msgid "Enable GIT"
 msgstr ""
 
+#: ../geanyvc/src/geanyvc.c:2110
+msgid "Enable Fossil"
+msgstr ""
+
 #: ../geanyvc/src/geanyvc.c:2106
 msgid "Enable SVN"
 msgstr ""


Modified: po/es.po
4 lines changed, 4 insertions(+), 0 deletions(-)
===================================================================
@@ -4829,6 +4829,10 @@ msgstr "Activar CVS"
 msgid "Enable GIT"
 msgstr "Activar GIT"
 
+#: ../geanyvc/src/geanyvc.c:2110
+msgid "Enable Fossil"
+msgstr "Activar Fossil"
+
 #: ../geanyvc/src/geanyvc.c:2106
 msgid "Enable SVN"
 msgstr "Activar SVN"


Modified: po/fr.po
4 lines changed, 4 insertions(+), 0 deletions(-)
===================================================================
@@ -4836,6 +4836,10 @@ msgstr "Activer CVS"
 msgid "Enable GIT"
 msgstr "Activer Git"
 
+#: ../geanyvc/src/geanyvc.c:2110
+msgid "Enable Fossil"
+msgstr "Activer Fossil"
+
 #: ../geanyvc/src/geanyvc.c:2106
 msgid "Enable SVN"
 msgstr "Activer SVN"


Modified: po/gl.po
4 lines changed, 4 insertions(+), 0 deletions(-)
===================================================================
@@ -4778,6 +4778,10 @@ msgstr "Habilitar CVS"
 msgid "Enable GIT"
 msgstr "Habilitar GIT"
 
+#: ../geanyvc/src/geanyvc.c:2110
+msgid "Enable Fossil"
+msgstr "Habilitar Fossil"
+
 #: ../geanyvc/src/geanyvc.c:2106
 msgid "Enable SVN"
 msgstr "Habilitar SVN"


Modified: po/it.po
4 lines changed, 4 insertions(+), 0 deletions(-)
===================================================================
@@ -4785,6 +4785,10 @@ msgstr "Abilita CVS"
 msgid "Enable GIT"
 msgstr "Abilita GIT"
 
+#: ../geanyvc/src/geanyvc.c:2110
+msgid "Enable Fossil"
+msgstr "Abilita Fossil"
+
 #: ../geanyvc/src/geanyvc.c:2106
 msgid "Enable SVN"
 msgstr "Abilita SVN"


Modified: po/ja.po
4 lines changed, 4 insertions(+), 0 deletions(-)
===================================================================
@@ -4706,6 +4706,10 @@ msgstr "CVSを有効"
 msgid "Enable GIT"
 msgstr "GITを有効"
 
+#: ../geanyvc/src/geanyvc.c:2110
+msgid "Enable Fossil"
+msgstr "Fossilを有効"
+
 #: ../geanyvc/src/geanyvc.c:2106
 msgid "Enable SVN"
 msgstr "SVNを有効"


Modified: po/kk.po
4 lines changed, 4 insertions(+), 0 deletions(-)
===================================================================
@@ -4511,6 +4511,10 @@ msgstr ""
 msgid "Enable GIT"
 msgstr ""
 
+#: ../geanyvc/src/geanyvc.c:2110
+msgid "Enable Fossil"
+msgstr ""
+
 #: ../geanyvc/src/geanyvc.c:2106
 msgid "Enable SVN"
 msgstr ""


Modified: po/nl.po
4 lines changed, 4 insertions(+), 0 deletions(-)
===================================================================
@@ -4576,6 +4576,10 @@ msgstr ""
 msgid "Enable GIT"
 msgstr ""
 
+#: ../geanyvc/src/geanyvc.c:2110
+msgid "Enable Fossil"
+msgstr ""
+
 #: ../geanyvc/src/geanyvc.c:2106
 msgid "Enable SVN"
 msgstr ""


Modified: po/pt.po
4 lines changed, 4 insertions(+), 0 deletions(-)
===================================================================
@@ -4817,6 +4817,10 @@ msgstr "Activar SCV"
 msgid "Enable GIT"
 msgstr "Activar GIT"
 
+#: ../geanyvc/src/geanyvc.c:2110
+msgid "Enable Fossil"
+msgstr "Activar Fossil"
+
 #: ../geanyvc/src/geanyvc.c:2106
 msgid "Enable SVN"
 msgstr "Activar SVN"


Modified: po/pt_BR.po
4 lines changed, 4 insertions(+), 0 deletions(-)
===================================================================
@@ -4789,6 +4789,10 @@ msgstr "Habilitar CVS"
 msgid "Enable GIT"
 msgstr "Habilitar GIT"
 
+#: ../geanyvc/src/geanyvc.c:2110
+msgid "Enable Fossil"
+msgstr "Habilitar Fossil"
+
 #: ../geanyvc/src/geanyvc.c:2106
 msgid "Enable SVN"
 msgstr "Habilitar SVN"


Modified: po/ru.po
4 lines changed, 4 insertions(+), 0 deletions(-)
===================================================================
@@ -4775,6 +4775,10 @@ msgstr "Включить CVS"
 msgid "Enable GIT"
 msgstr "Включить GIT"
 
+#: ../geanyvc/src/geanyvc.c:2110
+msgid "Enable Fossil"
+msgstr "Включить Fossil"
+
 #: ../geanyvc/src/geanyvc.c:2106
 msgid "Enable SVN"
 msgstr "Включить SVN"


Modified: po/tr.po
4 lines changed, 4 insertions(+), 0 deletions(-)
===================================================================
@@ -4678,6 +4678,10 @@ msgstr "CVS'i etkinleştir"
 msgid "Enable GIT"
 msgstr "GIT'i etkinleştir"
 
+#: ../geanyvc/src/geanyvc.c:2110
+msgid "Enable Fossil"
+msgstr "Fossil'i etkinleştir"
+
 #: ../geanyvc/src/geanyvc.c:2106
 msgid "Enable SVN"
 msgstr "SVN'i etkinleştir"


Modified: po/zh_CN.po
4 lines changed, 4 insertions(+), 0 deletions(-)
===================================================================
@@ -4775,6 +4775,10 @@ msgstr "启用 CVS"
 msgid "Enable GIT"
 msgstr "启用 GIT"
 
+#: ../geanyvc/src/geanyvc.c:2110
+msgid "Enable Fossil"
+msgstr "启用 Fossil"
+
 #: ../geanyvc/src/geanyvc.c:2106
 msgid "Enable SVN"
 msgstr "启用 SVN"



--------------
This E-Mail was brought to you by github_commit_mail.py (Source: https://github.com/geany/infrastructure).


More information about the Plugins-Commits mailing list