1 /*
2 * Copyright 2007-2011 Frank Lanitz <frank(at)frank(dot)uvena(dot)de>
3 * Copyright 2007-2009 Enrico Tröger <enrico.troeger@uvena.de>
4 * Copyright 2007 Nick Treleaven <nick.treleaven@btinternet.com>
5 * Copyright 2007-2009 Yura Siamashka <yurand2@gmail.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 */
21
22 #include <string.h>
23 #include <geanyplugin.h>
24 #include "geanyvc.h"
25
26 extern GeanyData *geany_data;
27
28
29 static const gchar *SVK_CMD_DIFF_FILE[] = { "svk", "diff", ABS_FILENAME, NULL };
30 static const gchar *SVK_CMD_DIFF_DIR[] = { "svk", "diff", ABS_DIRNAME, NULL };
31 static const gchar *SVK_CMD_REVERT_FILE[] = { "svk", "revert", BASENAME, NULL };
32 static const gchar *SVK_CMD_REVERT_DIR[] = { "svk", "revert", "--recursive", BASE_DIRNAME, NULL };
33 static const gchar *SVK_CMD_STATUS[] = { "svk", "status", NULL };
34 static const gchar *SVK_CMD_ADD[] = { "svk", "add", BASENAME, NULL };
35 static const gchar *SVK_CMD_REMOVE[] = { "svk", "remove", BASENAME, NULL };
36 static const gchar *SVK_CMD_LOG_FILE[] = { "svk", "log", BASENAME, NULL };
37 static const gchar *SVK_CMD_LOG_DIR[] = { "svk", "log", ABS_DIRNAME, NULL };
38 static const gchar *SVK_CMD_COMMIT[] = { "svk", "commit", "-m", MESSAGE, FILE_LIST, NULL };
39 static const gchar *SVK_CMD_BLAME[] = { "svk", "blame", BASENAME, NULL };
40 static const gchar *SVK_CMD_SHOW[] = { "svk", "cat", BASENAME, NULL };
41 static const gchar *SVK_CMD_UPDATE[] = { "svk", "up", NULL };
42
43 static const VC_COMMAND commands[] = {
44 {
45 VC_COMMAND_STARTDIR_FILE,
46 SVK_CMD_DIFF_FILE,
47 NULL,
48 NULL},
49 {
50 VC_COMMAND_STARTDIR_FILE,
51 SVK_CMD_DIFF_DIR,
52 NULL,
53 NULL},
54 {
55 VC_COMMAND_STARTDIR_FILE,
56 SVK_CMD_REVERT_FILE,
57 NULL,
58 NULL},
59 {
60 VC_COMMAND_STARTDIR_BASE,
61 SVK_CMD_REVERT_DIR,
62 NULL,
63 NULL},
64 {
65 VC_COMMAND_STARTDIR_FILE,
66 SVK_CMD_STATUS,
67 NULL,
68 NULL},
69 {
70 VC_COMMAND_STARTDIR_FILE,
71 SVK_CMD_ADD,
72 NULL,
73 NULL},
74 {
75 VC_COMMAND_STARTDIR_FILE,
76 SVK_CMD_REMOVE,
77 NULL,
78 NULL},
79 {
80 VC_COMMAND_STARTDIR_FILE,
81 SVK_CMD_LOG_FILE,
82 NULL,
83 NULL},
84 {
85 VC_COMMAND_STARTDIR_FILE,
86 SVK_CMD_LOG_DIR,
87 NULL,
88 NULL},
89 {
90 VC_COMMAND_STARTDIR_FILE,
91 SVK_CMD_COMMIT,
92 NULL,
93 NULL},
94 {
95 VC_COMMAND_STARTDIR_FILE,
96 SVK_CMD_BLAME,
97 NULL,
98 NULL},
99 {
100 VC_COMMAND_STARTDIR_FILE,
101 SVK_CMD_SHOW,
102 NULL,
103 NULL},
104 {
105 VC_COMMAND_STARTDIR_BASE,
106 SVK_CMD_UPDATE,
107 NULL,
108 NULL}
109 };
110
111
112 static gchar *
get_base_dir(const gchar * path)113 get_base_dir(const gchar * path)
114 {
115 /* NOT IMPLEMENTED */
116 return g_path_get_dirname(path);
117 }
118
119 static gboolean
in_vc_svk(const gchar * filename)120 in_vc_svk(const gchar * filename)
121 {
122 gint exit_code;
123 const gchar *argv[] = { "svk", "info", NULL, NULL };
124 gchar *dir;
125 gchar *base_name = NULL;
126 gboolean ret = FALSE;
127
128
129 if (g_file_test(filename, G_FILE_TEST_IS_DIR))
130 {
131 exit_code =
132 execute_custom_command(filename, (const gchar **) argv, NULL, NULL, NULL,
133 filename, NULL, NULL);
134
135 }
136 else
137 {
138 base_name = g_path_get_basename(filename);
139 dir = g_path_get_dirname(filename);
140
141 argv[2] = base_name;
142
143 exit_code = execute_custom_command(dir, (const gchar **) argv, NULL, NULL, NULL,
144 dir, NULL, NULL);
145
146 g_free(dir);
147 g_free(base_name);
148 }
149
150 if (exit_code == 0)
151 {
152 ret = TRUE;
153 }
154
155 return ret;
156 }
157
158 static GSList *
get_commit_files_svk(const gchar * dir)159 get_commit_files_svk(const gchar * dir)
160 {
161 enum
162 {
163 FIRST_CHAR,
164 SKIP_SPACE,
165 FILE_NAME,
166 };
167
168 gchar *txt;
169 GSList *ret = NULL;
170 gint pstatus = FIRST_CHAR;
171 const gchar *p;
172 gchar *base_name;
173 const gchar *start = NULL;
174 CommitItem *item;
175
176 const gchar *status = NULL;
177 gchar *filename;
178 const char *argv[] = { "svk", "status", NULL };
179
180 execute_custom_command(dir, argv, NULL, &txt, NULL, dir, NULL, NULL);
181 if (EMPTY(txt))
182 return NULL;
183 p = txt;
184
185 while (*p)
186 {
187 if (*p == '\r')
188 {
189 }
190 else if (pstatus == FIRST_CHAR)
191 {
192 status = NULL;
193 if (*p == '?')
194 status = FILE_STATUS_UNKNOWN;
195 else if (*p == 'M')
196 status = FILE_STATUS_MODIFIED;
197 else if (*p == 'D')
198 status = FILE_STATUS_DELETED;
199 else if (*p == 'A')
200 status = FILE_STATUS_ADDED;
201
202 if (!status || *(p + 1) != ' ')
203 {
204 /* skip unknown status line */
205 while (*p)
206 {
207 p++;
208 if (*p == '\n')
209 {
210 p++;
211 break;
212 }
213 }
214 pstatus = FIRST_CHAR;
215 continue;
216 }
217 pstatus = SKIP_SPACE;
218 }
219 else if (pstatus == SKIP_SPACE)
220 {
221 if (*p == ' ' || *p == '\t')
222 {
223 }
224 else
225 {
226 start = p;
227 pstatus = FILE_NAME;
228 }
229 }
230 else if (pstatus == FILE_NAME)
231 {
232 if (*p == '\n')
233 {
234 if (status != FILE_STATUS_UNKNOWN)
235 {
236 base_name = g_malloc0(p - start + 1);
237 memcpy(base_name, start, p - start);
238 filename = g_build_filename(dir, base_name, NULL);
239 g_free(base_name);
240 item = g_new(CommitItem, 1);
241 item->status = status;
242 item->path = filename;
243 ret = g_slist_append(ret, item);
244 }
245 pstatus = FIRST_CHAR;
246 }
247 }
248 p++;
249 }
250 g_free(txt);
251 return ret;
252 }
253
254 VC_RECORD VC_SVK = {
255 commands,
256 "svk",
257 get_base_dir,
258 in_vc_svk,
259 get_commit_files_svk,
260 };
261