ide.diff
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) |