ide.diff

Jan DolinĂ¡r, 03/23/2011 07:09 PM

Download (2.19 MB)

View differences:

usvn/usvn.lay (working copy)
1
LAYOUT(SvnSyncLayout, 672, 592)
1
LAYOUT(SvnSyncLayout, 680, 400)
2 2
	ITEM(ArrayCtrl, list, AutoHideSb(true).HSizePosZ(4, 4).VSizePosZ(4, 36))
3 3
	ITEM(Button, cancel, SetLabel(t_("Cancel")).LeftPosZ(4, 64).BottomPosZ(4, 24))
4
	ITEM(Button, setup, SetLabel(t_("Setup working directories")).LeftPosZ(88, 144).TopPosZ(564, 24))
4
	ITEM(Button, setup, SetLabel(t_("Setup working directories")).LeftPosZ(72, 144).BottomPosZ(4, 24))
5 5
	ITEM(Button, ok, SetLabel(t_("Synchronize!")).RightPosZ(4, 84).BottomPosZ(4, 24))
6 6
END_LAYOUT
7 7

  
......
23 23
	ITEM(EditString, user, LeftPosZ(100, 296).TopPosZ(56, 19))
24 24
	ITEM(Label, dv___6, SetLabel(t_("Password")).LeftPosZ(8, 88).TopPosZ(80, 20))
25 25
	ITEM(EditString, password, LeftPosZ(100, 296).TopPosZ(80, 19))
26
	ITEM(Option, readonly, SetLabel(t_("Read-only repository")).LeftPosZ(8, 184).TopPosZ(108, 16))
26 27
	ITEM(Button, ok, SetLabel(t_("OK")).LeftPosZ(264, 64).TopPosZ(108, 24))
27 28
	ITEM(Button, cancel, SetLabel(t_("Cancel")).LeftPosZ(332, 64).TopPosZ(108, 24))
28 29
END_LAYOUT
......
34 35
	ITEM(EditString, user, LeftPosZ(100, 296).TopPosZ(32, 19))
35 36
	ITEM(Label, dv___4, SetLabel(t_("Password")).LeftPosZ(8, 88).TopPosZ(56, 20))
36 37
	ITEM(EditString, password, LeftPosZ(100, 296).TopPosZ(56, 19))
38
	ITEM(Option, readonly, SetLabel(t_("Uses read-only repository")).LeftPosZ(8, 184).TopPosZ(80, 16))
37 39
	ITEM(Button, ok, SetLabel(t_("OK")).LeftPosZ(264, 64).TopPosZ(84, 24))
38 40
	ITEM(Button, cancel, SetLabel(t_("Cancel")).LeftPosZ(332, 64).TopPosZ(84, 24))
39 41
END_LAYOUT
40 42

  
41
LAYOUT(ConsoleLayout, 740, 544)
43
LAYOUT(ConsoleLayout, 680, 4500)
42 44
	ITEM(ArrayCtrl, list, HSizePosZ(4, 4).VSizePosZ(4, 32))
43 45
	ITEM(Button, exit, SetLabel(t_("Close")).RightPosZ(4, 64).BottomPosZ(4, 24))
44 46
END_LAYOUT
45 47

  
46
LAYOUT(SvnSelLayout, 608, 376)
48
LAYOUT(SvnSelLayout, 680, 400)
47 49
	ITEM(FileList, list, HSizePosZ(4, 4).VSizePosZ(28, 40))
48 50
	ITEM(Button, ok, SetLabel(t_("OK")).RightPosZ(72, 64).BottomPosZ(8, 24))
49 51
	ITEM(Button, cancel, SetLabel(t_("Cancel")).RightPosZ(4, 64).BottomPosZ(8, 24))
usvn/usvn.h (working copy)
1
#ifndef _usvn_usvn_h_
2
#define _usvn_usvn_h_
3

  
4
#include <TextDiffCtrl/TextDiffCtrl.h>
5

  
6
using namespace Upp;
7

  
8
#define LAYOUTFILE <usvn/usvn.lay>
9
#include <CtrlCore/lay.h>
10

  
11
class SysConsole : public WithConsoleLayout<TopWindow> {
12
	typedef SysConsole CLASSNAME;
13
	
14
	Font font;
15
	void AddResult(const String& out);
16

  
17
public:
18
	int  System(const char *s);
19
	int  CheckSystem(const char *s);
20
	void Perform()	                            { exit.Show(); Execute(); }
21

  
22
	SysConsole();
23
};
24

  
25
class SvnSel : public WithSvnSelLayout<TopWindow> {
26
	String url, usr, pwd;
27
	String folder;
28
	
29
	bool Load(const String& path);
30
	void SyncResult();
31
	void Go();
32
	void DirUp();
33
	bool NewUrl();
34
	void Url();
35
	bool TryLoad(const char *url);
36
	bool Select0();
37

  
38
	typedef SvnSel CLASSNAME;
39

  
40
public:
41
	bool Select();
42
	bool Select(const char *url, const char *user, const char *pwd);
43

  
44
	String GetUsername() const         { return usr; }
45
	String GetPassword() const         { return pwd; }
46
	String GetUrl() const              { return ~result; }
47
	
48
	SvnSel();
49
};
50

  
51
struct Repo {
52
	String repo;
53
	String work;
54
	String user;
55
	String pswd;
56

  
57
	void Save(String& s);
58
	void Load(CParser& p);
59
};
60

  
61
struct SvnWork {
62
	String working;
63
	String user;
64
	String password;
65
};
66

  
67
class SvnWorks : public WithSvnWorksLayout<TopWindow> {
68
	void New();
69
	void Edit();
70
	void Remove();
71
	void Checkout();
72
	void Sync();
73
	
74
	FrameRight<Button> dirsel;
75
	void DirSel(EditField& f);
76

  
77
public:
78
	void    Clear();
79
	void    Add(const String& working, const String& user, const String& data);
80
	void    Load(const String& text);
81
	String  Save() const;
82
	
83
	int     GetCount() const;
84
	SvnWork operator[](int i) const;
85

  
86
	typedef SvnWorks CLASSNAME;
87
	
88
	SvnWorks();
89
};
90

  
91
String SvnCmd(const char *cmd, const String& user, const String& pwd);
92
String SvnCmd(const char *cmd, const SvnWork& w);
93

  
94
bool   IsSvnDir(const String& p);
95

  
96
bool   CheckSvn();
97

  
98
struct SvnSync : WithSvnSyncLayout<TopWindow> {
99
	enum {
100
		MODIFY,
101
		CONFLICT,
102
		ADD,
103
		REMOVE,
104
		REPLACE,
105
		
106
		REPOSITORY,
107
		MESSAGE,
108
		
109
		DELETEC = -2
110
	};
111
	
112
	Array<Switch>            revert;
113
	Array<DocEdit>           message;
114
	Array<Button>            diff;
115
	ArrayMap<String, String> msgmap;
116
	
117
	SvnWorks works;
118
	
119
	void SyncList();
120
	void Setup();
121
	void DoDiff(int ii);
122
	void Diff();
123

  
124
	typedef SvnSync CLASSNAME;
125

  
126
public:
127
	void   SetMsgs(const String& s);
128
	String GetMsgs();
129

  
130
	void Dir(const char *dir);
131
	void Perform();
132
	void DoSync();
133
	
134
	SvnSync();
135
};
136

  
137
void RunSvnDiff(String editfile);
138

  
139
#endif
1
#ifndef _usvn_usvn_h_
2
#define _usvn_usvn_h_
3

  
4
#include <TextDiffCtrl/TextDiffCtrl.h>
5

  
6
using namespace Upp;
7

  
8
#define LAYOUTFILE <usvn/usvn.lay>
9
#include <CtrlCore/lay.h>
10

  
11
class SysConsole : public WithConsoleLayout<TopWindow> {
12
	typedef SysConsole CLASSNAME;
13
	
14
	Font font;
15
	void AddResult(const String& out);
16

  
17
public:
18
	int  System(const char *s);
19
	int  CheckSystem(const char *s);
20
	void Perform()	                            { exit.Show(); Execute(); }
21

  
22
	SysConsole();
23
};
24

  
25
class SvnSel : public WithSvnSelLayout<TopWindow> {
26
	String url, usr, pwd;
27
	String folder;
28
	
29
	bool Load(const String& path);
30
	void SyncResult();
31
	void Go();
32
	void DirUp();
33
	bool NewUrl();
34
	void Url();
35
	bool TryLoad(const char *url);
36
	bool Select0();
37

  
38
	typedef SvnSel CLASSNAME;
39

  
40
public:
41
	bool Select();
42
	bool Select(const char *url, const char *user, const char *pwd);
43

  
44
	String GetUsername() const         { return usr; }
45
	String GetPassword() const         { return pwd; }
46
	String GetUrl() const              { return ~result; }
47
	
48
	SvnSel();
49
};
50

  
51
struct Repo {
52
	String repo;
53
	String work;
54
	String user;
55
	String pswd;
56

  
57
	void Save(String& s);
58
	void Load(CParser& p);
59
};
60

  
61
struct SvnWork {
62
	String working;
63
	String user;
64
	String password;
65
	int revision;
66
	bool readonly;
67
};
68

  
69
class SvnWorks : public WithSvnWorksLayout<TopWindow> {
70
	void New();
71
	void Edit();
72
	void Remove();
73
	void Checkout();
74
	void Sync();
75
	
76
	FrameRight<Button> dirsel;
77
	void DirSel(EditField& f);
78

  
79
public:
80
	void    Clear();
81
	void    Add(const String& working, const String& user, const String& data, bool readonly=false);
82
	void    Load(const String& text);
83
	String  Save() const;
84
	
85
	int     GetCount() const;
86
	SvnWork operator[](int i) const;
87
	void SetRevision(int i, int revision);
88

  
89
	typedef SvnWorks CLASSNAME;
90
	
91
	SvnWorks();
92
};
93

  
94
String SvnCmd(const char *cmd, const String& user, const String& pwd, int rev=0);
95
String SvnCmd(const char *cmd, const SvnWork& w);
96

  
97
bool   IsSvnDir(const String& p);
98

  
99
bool   CheckSvn();
100

  
101
struct SvnSync : WithSvnSyncLayout<TopWindow> {
102
	enum {
103
		MODIFY,
104
		CONFLICT,
105
		ADD,
106
		REMOVE,
107
		REPLACE,
108
		
109
		REPOSITORY,
110
		MESSAGE,
111
		
112
		DELETEC = -2
113
	};
114
	
115
	Array<Switch>            revert;
116
	Array<DocEdit>           message;
117
	Array<Button>            diff;
118
	ArrayMap<String, String> msgmap;
119
	
120
	SvnWorks works;
121
	
122
	void SyncList();
123
	void Setup();
124
	void DoDiff(int ii);
125
	void Diff();
126

  
127
	typedef SvnSync CLASSNAME;
128

  
129
public:
130
	void   SetMsgs(const String& s);
131
	String GetMsgs();
132

  
133
	void Dir(const char *dir, bool readonly=false);
134
	void FixRevision(const char *dir, int revision);
135
	void Perform();
136
	void DoSync();
137
	
138
	SvnSync();
139
};
140

  
141
void RunSvnDiff(String editfile);
142

  
143
#endif
usvn/SvnSync.cpp (working copy)
1
#include "usvn.h"
2

  
3
bool CheckSvn()
4
{
5
	String h;
6
	if(Sys("svn", h) >= 0)
7
		return true;
8
#ifdef PLATFORM_WIN32
9
	Exclamation("Unable to execute svn.exe!&"
10
	            "You can download svn client here: [^http://www.sliksvn.com/en/download^ http://www.sliksvn.com/en/download]");
11
#else
12
	Exclamation("Unable to execute 'svn' binary!&Please install svn client.");
13
#endif
14
	return false;
15
}
16

  
17
SvnSync::SvnSync()
18
{
19
	CtrlLayoutOKCancel(*this, "SvnSynchronize SVN repositories");
20
	list.AddIndex();
21
	list.AddIndex();
22
	list.AddColumn("Action");
23
	list.AddColumn("Path");
24
	list.AddColumn("Changes");
25
	list.ColumnWidths("170 500 100");
26
	list.NoCursor().EvenRowColor();
27
	list.SetLineCy(max(Draw::GetStdFontCy(), 20));
28
	list.WhenLeftClick = THISBACK(Diff);
29
	Sizeable().Zoomable();
30
	setup <<= THISBACK(Setup);
31
	BackPaint();
32
}
33

  
34
void SvnSync::Setup()
35
{
36
	works.Execute();
37
	SyncList();
38
}
39

  
40
int CharFilterSvnMsg(int c)
41
{
42
	return c >= 32 && c < 128 && c != '\"' ? c : 0;
43
}
44

  
45
void SvnSync::SyncList()
46
{
47
	list.Clear();
48
	for(int i = 0; i < works.GetCount(); i++) {
49
		SvnWork w = works[i];
50
		String path = GetFullPath(w.working);
51
		list.Add(REPOSITORY, path,
52
		         AttrText("Working directory").SetFont(StdFont().Bold()).Ink(White).Paper(Blue),
53
		         AttrText(path).SetFont(Arial(20).Bold()).Paper(Blue).Ink(White),
54
		         AttrText("").SetFont(Arial(20).Bold()).Paper(Blue).Ink(White));
55
		list.SetLineCy(list.GetCount() - 1, 26);
56
		Vector<String> ln = Split(Sys("svn status " + path), CharFilterCrLf);
57
		bool actions = false;
58
		for(int pass = 0; pass < 2; pass++)
59
			for(int i = 0; i < ln.GetCount(); i++) {
60
				String h = ln[i];
61
				if(h.GetCount() > 7) {
62
					String file = TrimLeft(h.Mid(7));
63
					if(IsFullPath(file)) {
64
						actions = true;
65
						h.Trim(7);
66
						bool simple = h.Mid(1, 6) == "      ";
67
						int action = simple ? String("MC?!~").Find(h[0]) : -1;
68
						if(h == "    S  ")
69
							action = REPLACE;
70
						String an;
71
						Color  color;
72
						if(action < 0) {
73
							color = Black;
74
							if(simple && h[0] == 'A')
75
								an = "svn add";
76
							else
77
							if(simple && h[0] == 'D')
78
								an = "svn delete";
79
							else {
80
								an = h.Mid(0, 7);
81
								color = Gray;
82
							}
83
						}
84
						else {
85
							int q = file.ReverseFind('.');
86
							if(action == ADD && q >= 0 && (file.Mid(q + 1) == "mine" ||
87
							   file[q + 1] == 'r' && IsDigit(file[q + 2]))
88
							   && FileExists(file.Mid(0, q))) {
89
								action = DELETEC;
90
								an = "Delete";
91
								color = Black;
92
							}
93
							else {
94
								static const char *as[] = {
95
									"Modify", "Resolved", "Add", "Remove", "Replace"
96
								};
97
								static Color c[] = { LtBlue, Magenta, Green, LtRed, LtMagenta };
98
								an = as[action];
99
								color = c[action];
100
							}
101
						}
102
						if(pass == action < 0) {
103
							int ii = list.GetCount();
104
							list.Add(action, file,
105
							         action < 0 ? Value(AttrText(an).Ink(color)) : Value(true),
106
							         AttrText("  " + file.Mid(path.GetCount() + 1)).Ink(color));
107
							if(action >= 0) {
108
								list.SetCtrl(ii, 0, revert.Add().SetLabel("Revert\n" + an).NoWantFocus());
109
								Ctrl& b = diff.Add().SetLabel("Changes..").SizePos().NoWantFocus();
110
								b <<= THISBACK1(DoDiff, ii);
111
								list.SetCtrl(ii, 2, b);
112
							}
113
						}
114
					}
115
				}
116
		}
117
		if(actions) {
118
			list.Add(MESSAGE, Null, AttrText("Commit message:").SetFont(StdFont().Bold()));
119
			list.SetLineCy(list.GetCount() - 1, (3 * EditField::GetStdHeight()) + 4);
120
			list.SetCtrl(list.GetCount() - 1, 1, message.Add().SetFilter(CharFilterSvnMsg).VSizePos(2, 2).HSizePos());
121
			int q = msgmap.Find(w.working);
122
			if(q >= 0) {
123
				message.Top() <<= msgmap[q];
124
				msgmap.Unlink(q);
125
			}
126
		}
127
		else
128
			list.Add(-1, Null, "", AttrText("Nothing to do").SetFont(StdFont().Italic()));
129
	}
130
}
131

  
132
void SvnSync::DoDiff(int ii)
133
{
134
	String f = list.Get(ii, 1);
135
	if(!IsNull(f))
136
		RunSvnDiff(f);
137
}
138

  
139
void SvnSync::Diff()
140
{
141
	int cr = list.GetClickRow();
142
	if(cr >= 0)
143
		DoDiff(cr);
144
}
145

  
146
#ifdef PLATFORM_WIN32
147
void sDeleteFolderDeep(const char *dir)
148
{
149
	{
150
		FindFile ff(AppendFileName(dir, "*.*"));
151
		while(ff) {
152
			String name = ff.GetName();
153
			String p = AppendFileName(dir, name);
154
			if(ff.IsFile()) {
155
				SetFileAttributes(p, GetFileAttributes(p) & ~FILE_ATTRIBUTE_READONLY);
156
				FileDelete(p);
157
			}
158
			else
159
			if(ff.IsFolder())
160
				sDeleteFolderDeep(p);
161
			ff.Next();
162
		}
163
	}
164
	DirectoryDelete(dir);
165
}
166
#else
167
void sDeleteFolderDeep(const char *path)
168
{
169
	DeleteFolderDeep(path);
170
}
171
#endif
172

  
173
void SvnDel(const char *path)
174
{
175
	FindFile ff(AppendFileName(path, "*.*"));
176
	while(ff) {
177
		if(ff.IsFolder()) {
178
			String dir = AppendFileName(path, ff.GetName());
179
			if(ff.GetName() == ".svn")
180
				sDeleteFolderDeep(dir);
181
			else
182
				SvnDel(dir);
183
		}
184
		ff.Next();
185
	}
186
}
187

  
188
void SvnSync::Dir(const char *dir)
189
{
190
	setup.Hide();
191
	works.Add(dir, Null, Null);
192
}
193

  
194
void SvnSync::Perform()
195
{
196
	if(!CheckSvn())
197
		return;
198
	const Vector<String>& cl = CommandLine();
199
	if(cl.GetCount())
200
		for(int i = 0; i < cl.GetCount(); i++) {
201
			if(cl[i] == "-") {
202
				works.Load(LoadFile(ConfigFile("svnworks")));
203
				DoSync();
204
				SaveFile(ConfigFile("svnworks"), works.Save());
205
				return;
206
			}
207
			String d = GetFullPath(cl[i]);
208
			if(!DirectoryExists(cl[i])) {
209
				Cerr() << cl[i] << " not a directory\n";
210
				SetExitCode(1);
211
				return;
212
			}
213
			works.Add(d, "", "");
214
		}
215
	else
216
		works.Add(GetCurrentDirectory(), "", "");
217
	setup.Hide();
218
	DoSync();
219
}
220

  
221
void MoveSvn(const String& path, const String& tp)
222
{
223
	FindFile ff(AppendFileName(path, "*.*"));
224
	while(ff) {
225
		String nm = ff.GetName();
226
		String s = AppendFileName(path, nm);
227
		String t = AppendFileName(tp, nm);
228
		if(ff.IsFolder())
229
			if(nm == ".svn")
230
				FileMove(s, t);
231
			else
232
				MoveSvn(s, t);
233
		ff.Next();
234
	}
235
}
236

  
237
void SvnSync::DoSync()
238
{
239
	SyncList();
240
	msgmap.Sweep();
241
again:
242
	if(Execute() != IDOK || list.GetCount() == 0) {
243
		int repoi = 0;
244
		for(int i = 0; i < list.GetCount(); i++)
245
			if(list.Get(i, 0) == MESSAGE)
246
				msgmap.GetAdd(works[repoi++].working) = list.Get(i, 3);
247
		return;
248
	}
249
	bool changes = false;
250
	for(int i = 0; i < list.GetCount(); i++) {
251
		int action = list.Get(i, 0);
252
		Value v = list.Get(i, 2);
253
		if(action == MESSAGE) {
254
			if(changes && IsNull(list.Get(i, 3))
255
			&& !PromptYesNo("Commit message is empty.&Do you want to continue?"))
256
				goto again;
257
			changes = false;
258
		}
259
		else if(action != REPOSITORY && IsNumber(v) && (int)v)
260
			changes = true;
261
	}
262
	SysConsole sys;
263
	int repoi = 0;
264
	int l = 0;
265
	bool commit = false;
266
	while(l < list.GetCount()) {
267
		SvnWork w = works[repoi++];
268
		l++;
269
		String message;
270
		while(l < list.GetCount()) {
271
			int action = list.Get(l, 0);
272
			String path = list.Get(l, 1);
273
			if(action == MESSAGE && commit) {
274
				String msg = list.Get(l, 3);
275
				if(sys.CheckSystem(SvnCmd("commit", w).Cat() << w.working << " -m \"" << msg << "\""))
276
					msgmap.GetAdd(w.working) = msg;
277
				l++;
278
				break;
279
			}
280
			if(action == REPOSITORY)
281
				break;
282
			Value v = list.Get(l, 2);
283
			if(IsNumber(v) && (int)v == 0) {
284
				if(action == REPLACE || action == ADD)
285
					DeleteFolderDeep(path);
286
				if(action != ADD)
287
					sys.CheckSystem("svn revert " + path);
288
			}
289
			else {
290
				commit = true;
291
				switch(action) {
292
				case ADD:
293
					SvnDel(path);
294
					sys.CheckSystem("svn add --force " + path);
295
					break;
296
				case REMOVE:
297
					sys.CheckSystem("svn delete " + path);
298
					break;
299
				case CONFLICT:
300
					sys.CheckSystem("svn resolved " + path);
301
					break;
302
				case REPLACE: {
303
						SvnDel(path);
304
						String tp = AppendFileName(GetFileFolder(path), Format(Uuid::Create()));
305
						FileMove(path, tp);
306
						sys.CheckSystem(SvnCmd("update", w).Cat() << ' ' << path);
307
						MoveSvn(path, tp);
308
						sDeleteFolderDeep(path);
309
						FileMove(tp, path);
310
						Vector<String> ln = Split(Sys("svn status " + path), CharFilterCrLf);
311
						for(int l = 0; l < ln.GetCount(); l++) {
312
							String h = ln[l];
313
							if(h.GetCount() > 7) {
314
								String file = h.Mid(7);
315
								if(IsFullPath(file)) {
316
									h.Trim(7);
317
									if(h == "?      ")
318
										sys.CheckSystem("svn add --force " + file);
319
									if(h == "!      ")
320
										sys.CheckSystem("svn delete " + file);
321
								}
322
							}
323
						}
324
					}
325
					break;
326
				case DELETEC:
327
					FileDelete(path);
328
					break;
329
				}
330
			}
331
			l++;
332
		}
333
		sys.CheckSystem(SvnCmd("update", w).Cat() << w.working);
334
	}
335
	sys.Perform();
336
}
337

  
338
void SvnSync::SetMsgs(const String& s)
339
{
340
	LoadFromString(msgmap, s);
341
}
342

  
343
String SvnSync::GetMsgs()
344
{
345
	return StoreAsString(msgmap);
346
}
347

  
348
bool IsSvnDir(const String& p)
349
{
350
	return DirectoryExists(AppendFileName(p, ".svn")) || DirectoryExists(AppendFileName(p, "_svn"));
351
}
352

  
353
#ifdef flagMAIN
354
GUI_APP_MAIN
355
{
356
	if(!CheckSvn())
357
		return;
358
	SvnSync ss;
359
	String mp = ConfigFile("usvn.msg");
360
	ss.SetMsgs(LoadFile(mp));
361
	ss.Perform();
362
	SaveFile(mp, ss.GetMsgs());
363
}
364
#endif
1
#include "usvn.h"
2

  
3
bool CheckSvn()
4
{
5
	String h;
6
	if(Sys("svn", h) >= 0)
7
		return true;
8
#ifdef PLATFORM_WIN32
9
	Exclamation("Unable to execute svn.exe!&"
10
	            "You can download svn client here: [^http://www.sliksvn.com/en/download^ http://www.sliksvn.com/en/download]");
11
#else
12
	Exclamation("Unable to execute 'svn' binary!&Please install svn client.");
13
#endif
14
	return false;
15
}
16

  
17
SvnSync::SvnSync()
18
{
19
	CtrlLayoutOKCancel(*this, "SvnSynchronize SVN repositories");
20
	list.AddIndex();
21
	list.AddIndex();
22
	list.AddColumn("Action");
23
	list.AddColumn("Path");
24
	list.AddColumn("Changes");
25
	list.ColumnWidths("220 500 100");
26
	list.NoCursor().EvenRowColor();
27
	list.SetLineCy(max(Draw::GetStdFontCy(), 20));
28
	list.WhenLeftClick = THISBACK(Diff);
29
	Sizeable().Zoomable();
30
	setup <<= THISBACK(Setup);
31
	BackPaint();
32
}
33

  
34
void SvnSync::Setup()
35
{
36
	works.Execute();
37
	SyncList();
38
}
39

  
40
int CharFilterSvnMsg(int c)
41
{
42
	return c >= 32 && c < 128 && c != '\"' ? c : 0;
43
}
44

  
45
void SvnSync::SyncList()
46
{
47
	list.Clear();
48
	for(int i = 0; i < works.GetCount(); i++) {
49
		SvnWork w = works[i];
50
		String path = GetFullPath(w.working);
51
		list.Add(REPOSITORY, path,
52
		         AttrText("Working directory").SetFont(StdFont().Bold()).Ink(White).Paper(Blue),
53
		         AttrText(path).SetFont(Arial(20).Bold()).Paper(Blue).Ink(White),
54
		         AttrText("").SetFont(Arial(20).Bold()).Paper(Blue).Ink(White));
55
		list.SetLineCy(list.GetCount() - 1, 26);
56
		Vector<String> ln = Split(Sys("svn status " + path), CharFilterCrLf);
57
		bool actions = false;
58
		for(int pass = 0; pass < 2; pass++)
59
			for(int i = 0; i < ln.GetCount(); i++) {
60
				String h = ln[i];
61
				if(h.GetCount() > 7) {
62
					String file = TrimLeft(h.Mid(7));
63
					if(IsFullPath(file)) {
64
						actions = true;
65
						h.Trim(7);
66
						bool simple = h.Mid(1, 6) == "      ";
67
						int action = simple ? String("MC?!~").Find(h[0]) : -1;
68
						if(h == "    S  ")
69
							action = REPLACE;
70
						String an;
71
						Color  color;
72
						if(action < 0) {
73
							color = Black;
74
							if(simple && h[0] == 'A')
75
								an = "svn add";
76
							else
77
							if(simple && h[0] == 'D')
78
								an = "svn delete";
79
							else {
80
								an = h.Mid(0, 7);
81
								color = Gray;
82
							}
83
						}
84
						else {
85
							int q = file.ReverseFind('.');
86
							if(action == ADD && q >= 0 && (file.Mid(q + 1) == "mine" ||
87
							   file[q + 1] == 'r' && IsDigit(file[q + 2]))
88
							   && FileExists(file.Mid(0, q))) {
89
								action = DELETEC;
90
								an = "Delete";
91
								color = Black;
92
							}
93
							else {
94
								static const char *as[] = {
95
									"Modify", "Resolved", "Add", "Remove", "Replace"
96
								};
97
								static Color c[] = { LtBlue, Magenta, Green, LtRed, LtMagenta };
98
								an = as[action];
99
								color = c[action];
100
							}
101
						}
102
						if(pass == action < 0) {
103
							int ii = list.GetCount();
104
							list.Add(action, file,
105
							         action < 0 ? Value(AttrText(an).Ink(color)) : Value(true),
106
							         AttrText("  " + file.Mid(path.GetCount() + 1)).Ink(color));
107
							if(action >= 0) {
108
								list.SetCtrl(ii, 0, revert.Add().SetLabel("Revert\n" + an + "\nSkip").NoWantFocus());
109
								Ctrl& b = diff.Add().SetLabel("Changes..").SizePos().NoWantFocus();
110
								b <<= THISBACK1(DoDiff, ii);
111
								list.SetCtrl(ii, 2, b);
112
							}
113
						}
114
					}
115
				}
116
		}
117
		if(actions) {
118
			list.Add(MESSAGE, Null, AttrText("Commit message:").SetFont(StdFont().Bold()));
119
			list.SetLineCy(list.GetCount() - 1, (3 * EditField::GetStdHeight()) + 4);
120
			list.SetCtrl(list.GetCount() - 1, 1, message.Add().SetFilter(CharFilterSvnMsg).VSizePos(2, 2).HSizePos());
121
			int q = msgmap.Find(w.working);
122
			if(q >= 0) {
123
				message.Top() <<= msgmap[q];
124
				msgmap.Unlink(q);
125
			}
126
		}
127
		else
128
			list.Add(-1, Null, "", AttrText("Nothing to do").SetFont(StdFont().Italic()));
129
	}
130
}
131

  
132
void SvnSync::DoDiff(int ii)
133
{
134
	String f = list.Get(ii, 1);
135
	if(!IsNull(f))
136
		RunSvnDiff(f);
137
}
138

  
139
void SvnSync::Diff()
140
{
141
	int cr = list.GetClickRow();
142
	if(cr >= 0)
143
		DoDiff(cr);
144
}
145

  
146
#ifdef PLATFORM_WIN32
147
void sDeleteFolderDeep(const char *dir)
148
{
149
	{
150
		FindFile ff(AppendFileName(dir, "*.*"));
151
		while(ff) {
152
			String name = ff.GetName();
153
			String p = AppendFileName(dir, name);
154
			if(ff.IsFile()) {
155
				SetFileAttributes(p, GetFileAttributes(p) & ~FILE_ATTRIBUTE_READONLY);
156
				FileDelete(p);
157
			}
158
			else
159
			if(ff.IsFolder())
160
				sDeleteFolderDeep(p);
161
			ff.Next();
162
		}
163
	}
164
	DirectoryDelete(dir);
165
}
166
#else
167
void sDeleteFolderDeep(const char *path)
168
{
169
	DeleteFolderDeep(path);
170
}
171
#endif
172

  
173
void SvnDel(const char *path)
174
{
175
	FindFile ff(AppendFileName(path, "*.*"));
176
	while(ff) {
177
		if(ff.IsFolder()) {
178
			String dir = AppendFileName(path, ff.GetName());
179
			if(ff.GetName() == ".svn")
180
				sDeleteFolderDeep(dir);
181
			else
182
				SvnDel(dir);
183
		}
184
		ff.Next();
185
	}
186
}
187

  
188
void SvnSync::Dir(const char *dir, bool readonly)
189
{
190
	setup.Hide();
191
	works.Add(dir, Null, Null, readonly);
192
}
193

  
194
void SvnSync::FixRevision(const char *dir, int revision){
195
	for(int i=0;i<works.GetCount();i++)
196
		if(works[i].working==dir){
197
			works.SetRevision(i,revision);
198
			return;
199
		}
200
}
201

  
202
void SvnSync::Perform()
203
{
204
	if(!CheckSvn())
205
		return;
206
	const Vector<String>& cl = CommandLine();
207
	if(cl.GetCount())
208
		for(int i = 0; i < cl.GetCount(); i++) {
209
			if(cl[i] == "-") {
210
				works.Load(LoadFile(ConfigFile("svnworks")));
211
				DoSync();
212
				SaveFile(ConfigFile("svnworks"), works.Save());
213
				return;
214
			}
215
			String d = GetFullPath(cl[i]);
216
			if(!DirectoryExists(cl[i])) {
217
				Cerr() << cl[i] << " not a directory\n";
218
				SetExitCode(1);
219
				return;
220
			}
221
			works.Add(d, "", "");
222
		}
223
	else
224
		works.Add(GetCurrentDirectory(), "", "");
225
	setup.Hide();
226
	DoSync();
227
}
228

  
229
void MoveSvn(const String& path, const String& tp)
230
{
231
	FindFile ff(AppendFileName(path, "*.*"));
232
	while(ff) {
233
		String nm = ff.GetName();
234
		String s = AppendFileName(path, nm);
235
		String t = AppendFileName(tp, nm);
236
		if(ff.IsFolder())
237
			if(nm == ".svn")
238
				FileMove(s, t);
239
			else
240
				MoveSvn(s, t);
241
		ff.Next();
242
	}
243
}
244

  
245
void SvnSync::DoSync()
246
{
247
	SyncList();
248
	msgmap.Sweep();
249
again:
250
	if(Execute() != IDOK || list.GetCount() == 0) {
251
		int repoi = 0;
252
		for(int i = 0; i < list.GetCount(); i++)
253
			if(list.Get(i, 0) == MESSAGE)
254
				msgmap.GetAdd(works[repoi++].working) = list.Get(i, 3);
255
		return;
256
	}
257
	bool changes = false;
258
	for(int i = 0; i < list.GetCount(); i++) {
259
		int action = list.Get(i, 0);
260
		Value v = list.Get(i, 2);
261
		if(action == MESSAGE) {
262
			if(changes && IsNull(list.Get(i, 3))
263
			&& !PromptYesNo("Commit message is empty.&Do you want to continue?"))
264
				goto again;
265
			changes = false;
266
		}
267
		else if(action != REPOSITORY && IsNumber(v) && v==1)
268
			changes = true;
269
	}
270
	SysConsole sys;
271
	int repoi = 0;
272
	int l = 0;
273
	bool commit = false;
274
	while(l < list.GetCount()) {
275
		SvnWork w = works[repoi++];
276
		l++;
277
		String message;
278
		String filelist;   // <-- list of files to update
279
		while(l < list.GetCount()) {
280
			int action = list.Get(l, 0);
281
			String path = list.Get(l, 1);
282
			if(action == MESSAGE && commit) {
283
				String msg = list.Get(l, 3);
284
				// now we commit only files in filelist
285
				if(sys.CheckSystem(SvnCmd("commit", w).Cat() << filelist << " -m \"" << msg << "\""))
286
					msgmap.GetAdd(w.working) = msg;
287
				l++;
288
				break;
289
			}
290
			if(action == REPOSITORY)
291
				break;
292
			Value v = list.Get(l, 2);
293
			if(IsNumber(v) && (int)v == 0) {
294
				if(action == REPLACE || action == ADD)
295
					DeleteFolderDeep(path);
296
				if(action != ADD)
297
					sys.CheckSystem("svn revert " + path);
298
			}else if(IsNumber(v)&&(int)v==2||action==-1){
299
				l++;
300
				continue;
301
			}
302
			else {
303
				filelist+=" "+path;   // <-- add the file to the list
304
				commit = true;
305
				switch(action) {
306
				case ADD:
307
					SvnDel(path);
308
					sys.CheckSystem("svn add --force " + path);
309
					break;
310
				case REMOVE:
311
					sys.CheckSystem("svn delete " + path);
312
					break;
313
				case CONFLICT:
314
					sys.CheckSystem("svn resolved " + path);
315
					break;
316
				case REPLACE: {
317
						SvnDel(path);
318
						String tp = AppendFileName(GetFileFolder(path), Format(Uuid::Create()));
319
						FileMove(path, tp);
320
						sys.CheckSystem(SvnCmd("update", w).Cat() << ' ' << path);
321
						MoveSvn(path, tp);
322
						sDeleteFolderDeep(path);
323
						FileMove(tp, path);
324
						Vector<String> ln = Split(Sys("svn status " + path), CharFilterCrLf);
325
						for(int l = 0; l < ln.GetCount(); l++) {
326
							String h = ln[l];
327
							if(h.GetCount() > 7) {
328
								String file = h.Mid(7);
329
								if(IsFullPath(file)) {
330
									h.Trim(7);
331
									if(h == "?      ")
332
										sys.CheckSystem("svn add --force " + file);
333
									if(h == "!      ")
334
										sys.CheckSystem("svn delete " + file);
335
								}
336
							}
337
						}
338
					}
339
					break;
340
				case DELETEC:
341
					FileDelete(path);
342
					break;
343
				}
344
			}
345
			l++;
346
		}
347
		sys.CheckSystem(SvnCmd("update", w).Cat() << w.working);
348
	}
349
	sys.Perform();
350
}
351

  
352
void SvnSync::SetMsgs(const String& s)
353
{
354
	LoadFromString(msgmap, s);
355
}
356

  
357
String SvnSync::GetMsgs()
358
{
359
	return StoreAsString(msgmap);
360
}
361

  
362
bool IsSvnDir(const String& p)
363
{
364
	return DirectoryExists(AppendFileName(p, ".svn")) || DirectoryExists(AppendFileName(p, "_svn"));
365
}
366

  
367
#ifdef flagMAIN
368
GUI_APP_MAIN
369
{
370
	if(!CheckSvn())
371
		return;
372
	SvnSync ss;
373
	String mp = ConfigFile("usvn.msg");
374
	ss.SetMsgs(LoadFile(mp));
375
	ss.Perform();
376
	SaveFile(mp, ss.GetMsgs());
377
}
378
#endif
usvn/SvnWorks.cpp (working copy)
1
#include "usvn.h"
2

  
3
static FileSel& ssSD() {
4
	static FileSel fs;
5
	ONCELOCK {
6
		fs.AllFilesType();
7
	}
8
	return fs;
9
}
10

  
11
static void sSetFolder(EditField *f)
12
{
13
	if(!ssSD().ExecuteSelectDir()) return;
14
	String path = ~ssSD();
15
	*f <<= IsNull(path) ? path : NormalizePath(path);
16
}
17

  
18
void SvnWorks::DirSel(EditField& f)
19
{
20
	f.AddFrame(dirsel);
21
	dirsel <<= callback1(&sSetFolder, &f);
22
	dirsel.SetImage(CtrlImg::smallright()).NoWantFocus();
23
}
24

  
25

  
26
void SvnWorks::Add(const String& working, const String& user, const String& data)
27
{
28
	list.Add(working, user, data);
29
	Sync();
30
}
31

  
32
void SvnWorks::New()
33
{
34
	WithSvnFolderLayout<TopWindow> dlg;
35
	CtrlLayoutOKCancel(dlg, "Add SVN working directory");
36
	DirSel(dlg.working);
37
	if(dlg.Execute() != IDOK)
38
		return;
39
	Add(~dlg.working, ~dlg.user, ~dlg.password);
40
}
41

  
42
void SvnWorks::Edit()
43
{
44
	if(!list.IsCursor())
45
		return;
46
	WithSvnFolderLayout<TopWindow> dlg;
47
	CtrlLayoutOKCancel(dlg, "Edit SVN working directory item");
48
	DirSel(dlg.working);
49
	dlg.working <<= list.Get(0);
50
	dlg.user <<= list.Get(1);
51
	dlg.password <<= list.Get(2);
52
	if(dlg.Execute() != IDOK)
53
		return;
54
	list.Set(0, ~dlg.working);
55
	list.Set(1, ~dlg.user);
56
	list.Set(2, ~dlg.password);
57
	Sync();
58
}
59

  
60
String SvnCmd(const char *cmd, const String& user, const String& pwd)
61
{
62
	String r = "svn ";
63
	r << cmd;
64
	r << " --non-interactive";
65
	if(!IsNull(user))
66
		r << " --username \"" << user << "\"";
67
	if(!IsNull(pwd))
68
		r << " --password \"" << pwd << "\"";
69
	r << ' ';
70
	return r;
71
}
72

  
73
String SvnCmd(const char *cmd, const SvnWork& w)
74
{
75
	return SvnCmd(cmd, w.user, w.password);
76
}
77

  
78
void SvnWorks::Checkout()
79
{
80
	WithSvnCheckoutLayout<TopWindow> dlg;
81
	CtrlLayoutOKCancel(dlg, "Checkout SVN repository");
82
	DirSel(dlg.working);
83
	if(dlg.Execute() != IDOK)
84
		return;
85
	String working = ~dlg.working;
86
	working = GetFullPath(working);
87
	if(working.GetCount() == 0) {
88
		Exclamation("Empty working directory");
89
		return;
90
	}
91
	RealizeDirectory(working);
92
	Add(~dlg.working, ~dlg.user, ~dlg.password);
93
	SysConsole con;
94
	con.System(SvnCmd("checkout", ~dlg.user, ~dlg.password).Cat() << ~dlg.repository << ' ' << ~dlg.working);
95
	con.Execute();
96
}
97

  
98
void SvnWorks::Remove()
99
{
100
	if(list.IsCursor() && PromptYesNo("Remove the item?"))
101
		list.Remove(list.GetCursor());
102
	Sync();
103
}
104

  
105
void SvnWorks::Sync()
106
{
107
	edit.Enable(list.IsCursor());
108
	remove.Enable(list.IsCursor());
109
}
110

  
111
int SvnWorks::GetCount() const
112
{
113
	return list.GetCount();
114
}
115

  
116
SvnWork SvnWorks::operator[](int i) const
117
{
118
	SvnWork w;
119
	w.working = list.Get(i, 0);
120
	w.user = list.Get(i, 1);
121
	w.password = list.Get(i, 2);
122
	return w;
123
}
124

  
125
void SvnWorks::Clear()
126
{
127
	list.Clear();
128
	Sync();
129
}
130

  
131
void SvnWorks::Load(const String& text)
132
{
133
	list.Clear();
134
	Vector<String> ln = Split(text, CharFilterCrLf);
135
	for(int i = 0; i < ln.GetCount(); i++) {
136
		Vector<String> q = Split(ln[i], ';');
137
		if(q.GetCount() >= 1)
138
			Add(q[0], q.At(1), q.At(2));
139
	}
140
	Sync();
141
}
142

  
143
String SvnWorks::Save() const
144
{
145
	String h;
146
	for(int i = 0; i < list.GetCount(); i++)
147
		h << list.Get(i, 0) << ';' << list.Get(i, 1) << ';' << list.Get(i, 2) << '\n';
148
	return h;
149
}
150

  
151
SvnWorks::SvnWorks()
152
{
153
	CtrlLayoutExit(*this, "SVN Working directories");
154
	list.AddColumn("Working directory");
155
	list.AddColumn("User");
156
	list.AddColumn("Password");
157
	list.Moving();
158
	list.ColumnWidths("364 100 100");
159
	list.WhenCursor = THISBACK(Sync);
160
	add <<= THISBACK(New);
161
	remove <<= THISBACK(Remove);
162
	checkout <<= THISBACK(Checkout);
163
	edit <<= THISBACK(Edit);
164
	Sync();
165
}
166

  
1
#include "usvn.h"
2

  
3
static FileSel& ssSD() {
4
	static FileSel fs;
5
	ONCELOCK {
6
		fs.AllFilesType();
7
	}
8
	return fs;
9
}
10

  
11
static void sSetFolder(EditField *f)
12
{
13
	if(!ssSD().ExecuteSelectDir()) return;
14
	String path = ~ssSD();
15
	*f <<= IsNull(path) ? path : NormalizePath(path);
16
}
17

  
18
void SvnWorks::DirSel(EditField& f)
19
{
20
	f.AddFrame(dirsel);
21
	dirsel <<= callback1(&sSetFolder, &f);
22
	dirsel.SetImage(CtrlImg::smallright()).NoWantFocus();
23
}
24

  
25

  
26
void SvnWorks::Add(const String& working, const String& user, const String& data, bool readonly)
27
{
28
	list.Add(working, user, data, readonly?"yes":"no",0);
29
	Sync();
30
}
31

  
32
void SvnWorks::New()
33
{
34
	WithSvnFolderLayout<TopWindow> dlg;
35
	CtrlLayoutOKCancel(dlg, "Add SVN working directory");
36
	DirSel(dlg.working);
37
	if(dlg.Execute() != IDOK)
38
		return;
39
	Add(~dlg.working, ~dlg.user, ~dlg.password, ~dlg.readonly);
40
}
41

  
42
void SvnWorks::Edit()
43
{
44
	if(!list.IsCursor())
45
		return;
46
	WithSvnFolderLayout<TopWindow> dlg;
47
	CtrlLayoutOKCancel(dlg, "Edit SVN working directory item");
48
	DirSel(dlg.working);
49
	dlg.working <<= list.Get(0);
50
	dlg.user <<= list.Get(1);
51
	dlg.password <<= list.Get(2);
52
	dlg.readonly <<= (AsString(list.Get(3))=="yes");
53
	if(dlg.Execute() != IDOK)
54
		return;
55
	list.Set(0, ~dlg.working);
56
	list.Set(1, ~dlg.user);
57
	list.Set(2, ~dlg.password);
58
	list.Set(3, ~dlg.readonly?"yes":"no");
59
	Sync();
60
}
61

  
62
String SvnCmd(const char *cmd, const String& user, const String& pwd,int rev)
63
{
64
	String r = "svn ";
65
	r << cmd;
66
	r << " --non-interactive";
67
	if(!IsNull(user))
68
		r << " --username \"" << user << "\"";
69
	if(!IsNull(pwd))
70
		r << " --password \"" << pwd << "\"";
71
	if(rev!=0)
72
		r << " --revision " << rev;
73
	r << ' ';
74
	return r;
75
}
76

  
77
String SvnCmd(const char *cmd, const SvnWork& w)
78
{
79
	return SvnCmd(cmd, w.user, w.password, w.revision);
80
}
81

  
82
void SvnWorks::Checkout()
83
{
84
	WithSvnCheckoutLayout<TopWindow> dlg;
85
	CtrlLayoutOKCancel(dlg, "Checkout SVN repository");
86
	DirSel(dlg.working);
87
	if(dlg.Execute() != IDOK)
88
		return;
89
	String working = ~dlg.working;
90
	working = GetFullPath(working);
91
	if(working.GetCount() == 0) {
92
		Exclamation("Empty working directory");
93
		return;
94
	}
95
	RealizeDirectory(working);
96
	Add(~dlg.working, ~dlg.user, ~dlg.password);
97
	SysConsole con;
98
	con.System(SvnCmd("checkout", ~dlg.user, ~dlg.password).Cat() << ~dlg.repository << ' ' << ~dlg.working);
99
	con.Execute();
100
}
101

  
102
void SvnWorks::Remove()
103
{
104
	if(list.IsCursor() && PromptYesNo("Remove the item?"))
105
		list.Remove(list.GetCursor());
106
	Sync();
107
}
108

  
109
void SvnWorks::Sync()
110
{
111
	edit.Enable(list.IsCursor());
112
	remove.Enable(list.IsCursor());
113
}
114

  
115
int SvnWorks::GetCount() const
116
{
117
	return list.GetCount();
118
}
119

  
120
SvnWork SvnWorks::operator[](int i) const
121
{
122
	SvnWork w;
123
	w.working = list.Get(i, 0);
124
	w.user = list.Get(i, 1);
125
	w.password = list.Get(i, 2);
126
	w.readonly = AsString(list.Get(i, 3))=="yes";
127
	w.revision = (int)list.Get(i,4);
128
	return w;
129
}
130

  
131
void SvnWorks::SetRevision(int i, int revision)
132
{
133
	list.Set(i,4,revision);
134
}
135

  
136
void SvnWorks::Clear()
137
{
138
	list.Clear();
139
	Sync();
140
}
141

  
142
void SvnWorks::Load(const String& text)
143
{
144
	list.Clear();
145
	Vector<String> ln = Split(text, CharFilterCrLf);
146
	for(int i = 0; i < ln.GetCount(); i++) {
147
		Vector<String> q = Split(ln[i], ';');
148
		if(q.GetCount() >= 1)
149
			Add(q[0], q.At(1), q.At(2), q.At(3)!="no");
150
	}
151
	Sync();
152
}
153

  
154
String SvnWorks::Save() const
155
{
156
	String h;
157
	for(int i = 0; i < list.GetCount(); i++)
158
		h << list.Get(i, 0) << ';' << list.Get(i, 1) << ';' << list.Get(i, 2) << ';' << list.Get(i, 3) << '\n';
159
	return h;
160
}
161

  
162
SvnWorks::SvnWorks()
163
{
164
	CtrlLayoutExit(*this, "SVN Working directories");
165
	list.AddColumn("Working directory");
166
	list.AddColumn("User");
167
	list.AddColumn("Password");
168
	list.AddColumn("Read-only");
169
	list.AddIndex("revision");
170
	list.Moving();
171
	list.ColumnWidths("364 100 100 100");
172
	list.WhenCursor = THISBACK(Sync);
173
	add <<= THISBACK(New);
174
	remove <<= THISBACK(Remove);
175
	checkout <<= THISBACK(Checkout);
176
	edit <<= THISBACK(Edit);
177
	Sync();
178
}
179

  
usvn/usvn.upp (working copy)
1
description "Simple svn GUI frontend, also a module that can be used in other applications";
1
description "Simple svn GUI frontend, also a module that can be used in other applications\377";
2 2

  
3 3
uses
4 4
	TextDiffCtrl;
ide/ide.iml (working copy)
36 36
IMAGE_ID(build_compile)
37 37
IMAGE_ID(build_rebuild_all)
38 38
IMAGE_ID(build_batch_build)
39
IMAGE_ID(install_updates)
40
IMAGE_ID(check_updates)
39 41
IMAGE_ID(sort_asc)
40 42
IMAGE_ID(debug_output)
41 43
IMAGE_ID(clean_package)
......
144 146
IMAGE_END_DATA(1056, 18)
145 147

  
146 148
IMAGE_BEGIN_DATA
147
IMAGE_DATA(120,156,236,157,5,156,148,85,23,135,87,5,233,238,6,65,64,74,90,65,80,17,20,69,186,187,187,20,20,44,76,84)
148
IMAGE_DATA(4,9,17,105,148,238,238,70,16,65,177,91,81,62,19,65,122,115,118,250,255,157,115,223,185,179,239,190,59,179,51,27)
149
IMAGE_DATA(244,121,252,29,167,222,218,217,101,158,57,55,206,141,200,29,145,59,2,136,72,71,94,65,218,30,95,233,253,130,29,199)
150
IMAGE_DATA(250,90,176,251,137,72,229,53,250,247,67,194,235,214,72,238,121,235,254,214,109,173,231,78,242,124,162,253,1,152,206,151)
151
IMAGE_DATA(240,56,216,243,230,253,173,219,134,121,107,221,63,197,183,230,253,83,202,181,116,254,52,68,218,73,205,135,193,43,116,114)
152
IMAGE_DATA(21,175,36,247,15,41,244,190,201,237,239,223,206,116,158,112,247,245,31,131,183,51,31,39,5,251,6,61,70,10,127,230)
153
IMAGE_DATA(64,215,144,162,253,45,215,157,146,99,88,247,181,62,31,96,151,68,127,96,175,36,254,153,147,188,102,121,78,237,111,70)
154
IMAGE_DATA(239,155,218,127,140,122,95,235,243,129,110,3,157,63,53,255,24,195,61,223,229,58,127,26,34,237,132,247,97,144,196,66)
155
IMAGE_DATA(41,253,248,80,251,155,255,48,82,112,12,191,201,146,121,19,3,238,151,240,199,20,120,255,32,199,48,253,146,3,153,56)
156
IMAGE_DATA(217,235,8,240,90,240,125,35,2,191,151,65,143,97,221,47,212,245,7,185,206,176,174,223,122,63,153,253,130,94,127,168)
157
IMAGE_DATA(253,130,157,63,220,235,79,238,252,201,93,71,144,253,2,30,35,133,251,37,251,62,132,185,95,162,99,164,114,191,212,145)
158
IMAGE_DATA(254,105,66,88,164,229,135,68,144,251,41,221,55,165,199,8,182,93,114,207,39,251,135,0,253,199,22,226,3,33,216,49)
159
IMAGE_DATA(232,21,181,47,223,90,247,13,112,254,160,199,72,193,190,41,250,71,116,53,246,15,51,146,35,45,251,134,58,70,74,72)
160
IMAGE_DATA(203,190,169,35,200,135,65,162,79,235,0,247,147,187,64,124,237,251,143,239,99,247,110,21,124,255,240,97,36,138,0,199)
161
IMAGE_DATA(240,239,167,247,13,112,206,132,184,37,201,49,66,158,219,191,159,142,100,246,79,246,188,129,247,15,116,140,164,239,109,240)
162
IMAGE_DATA(125,19,182,9,252,62,167,246,15,51,208,125,197,182,119,34,192,145,154,253,245,190,33,142,145,150,253,131,61,151,232,61)
163
IMAGE_DATA(72,229,190,161,8,246,190,7,59,118,56,251,39,119,109,161,142,145,210,125,173,231,14,253,115,103,138,200,26,236,155,65)
164
IMAGE_DATA(184,127,32,87,227,181,80,159,220,161,62,149,67,126,160,37,122,20,206,215,167,0,223,105,195,66,111,127,240,224,193,68)
165
IMAGE_DATA(17,206,113,204,251,89,126,168,68,199,73,110,223,136,224,111,132,255,56,214,215,45,251,70,36,105,148,48,61,182,110,27)
166
IMAGE_DATA(236,57,235,254,193,182,13,180,111,160,243,6,187,222,96,215,30,44,146,219,63,208,207,28,232,189,72,238,252,161,246,15)
167
IMAGE_DATA(245,30,132,186,254,112,223,255,96,239,95,176,109,245,243,193,254,78,205,127,215,129,126,87,122,51,235,223,187,245,223,67)
168
IMAGE_DATA(68,120,255,88,147,252,251,177,236,19,206,167,97,168,115,25,207,95,165,92,74,16,132,107,141,48,62,12,146,251,154,18)
169
IMAGE_DATA(114,63,24,121,127,146,8,113,156,96,219,38,57,102,128,99,36,121,61,192,55,155,228,142,145,236,190,129,142,97,218,63)
170
IMAGE_DATA(232,185,253,215,158,252,53,36,247,62,133,243,51,36,251,126,7,219,55,212,254,161,246,13,247,252,87,224,245,36,191,131)
171
IMAGE_DATA(20,252,236,1,255,126,82,177,127,208,99,132,185,175,255,24,225,188,31,65,246,77,114,156,0,145,148,203,253,97,16,244)
172
IMAGE_DATA(191,80,95,143,2,111,155,244,152,1,126,17,214,215,173,132,56,70,178,251,6,60,134,249,43,91,144,115,235,107,15,113)
173
IMAGE_DATA(13,201,189,79,225,252,12,201,190,223,65,247,13,181,127,168,125,195,60,255,21,120,61,233,239,32,252,159,61,240,223,79)
174
IMAGE_DATA(202,247,15,122,140,48,247,77,56,70,234,255,253,36,61,206,181,240,97,128,212,125,178,5,221,47,200,113,2,238,27,50)
175
IMAGE_DATA(231,12,97,6,149,99,6,57,117,144,253,19,109,20,238,249,205,239,135,117,255,96,164,100,255,64,109,54,87,243,252,105)
176
IMAGE_DATA(249,249,141,231,34,130,237,159,228,247,23,104,95,235,254,201,253,254,83,241,247,147,214,191,223,244,248,247,147,228,56,1)
177
IMAGE_DATA(34,41,63,221,50,230,22,188,172,127,2,65,16,4,65,16,4,65,16,4,65,16,4,65,16,4,65,16,4,65,16,4)
178
IMAGE_DATA(65,16,4,65,16,4,65,16,4,65,16,4,65,16,4,65,16,4,65,16,4,65,16,4,65,16,4,65,16,4,65,16)
149
IMAGE_DATA(120,156,236,157,5,156,148,213,247,135,71,5,233,238,20,4,1,41,105,5,65,69,80,20,233,238,238,82,80,176,48,81)
150
IMAGE_DATA(17,36,68,164,81,186,187,27,65,4,187,227,39,202,223,68,145,222,156,157,254,254,207,185,239,220,217,119,223,157,217,153)
151
IMAGE_DATA(13,250,60,126,142,83,111,237,236,50,207,156,27,231,218,242,218,242,218,0,91,6,242,50,210,247,248,114,239,23,234,56)
152
IMAGE_DATA(214,215,66,221,79,66,26,175,49,176,31,18,95,183,70,74,207,91,247,183,110,107,61,119,178,231,147,236,15,192,116,190)
153
IMAGE_DATA(196,199,161,158,55,239,111,221,54,194,91,235,254,169,190,53,239,159,90,174,166,243,167,35,210,79,90,62,12,94,166,147)
154
IMAGE_DATA(171,120,57,165,127,72,225,247,77,105,255,192,118,166,243,68,186,111,224,24,188,157,249,56,169,216,55,228,49,82,249,51)
155
IMAGE_DATA(7,187,134,84,237,111,185,238,212,28,195,186,175,245,249,32,187,36,249,3,123,57,233,207,156,236,53,203,115,106,127,51)
156
IMAGE_DATA(122,223,180,254,99,212,251,90,159,15,118,27,236,252,105,249,199,24,233,249,46,213,249,211,17,233,39,178,15,131,100,22)
157
IMAGE_DATA(74,237,199,135,218,223,252,135,145,138,99,4,76,150,194,155,24,116,191,196,63,166,224,251,135,56,134,233,151,28,204,196)
158
IMAGE_DATA(41,94,71,144,215,66,239,107,11,254,94,134,60,134,117,191,112,215,31,226,58,35,186,126,235,253,20,246,11,121,253,225)
159
IMAGE_DATA(246,11,117,254,72,175,63,165,243,167,116,29,33,246,11,122,140,84,238,151,226,251,16,225,126,73,142,145,198,253,210,70)
160
IMAGE_DATA(198,167,9,17,145,158,31,18,33,238,167,118,223,212,30,35,212,118,41,61,159,226,31,2,244,31,91,152,15,132,80,199)
161
IMAGE_DATA(160,87,212,190,124,107,221,55,200,249,67,30,35,21,251,166,234,31,209,149,216,63,194,72,137,244,236,27,238,24,169,33)
162
IMAGE_DATA(61,251,166,141,16,31,6,73,62,173,131,220,79,233,2,241,181,255,63,190,143,61,123,84,240,253,35,71,144,36,130,28)
163
IMAGE_DATA(35,176,159,222,55,200,57,19,227,166,100,199,8,123,238,192,126,58,82,216,63,197,243,6,223,63,216,49,146,191,183,161)
164
IMAGE_DATA(247,77,220,38,248,251,156,214,63,204,96,247,21,219,223,182,129,35,45,251,235,125,195,28,35,61,251,135,122,46,201,123)
... This diff was truncated because it exceeds the maximum size that can be displayed.