1 #include "TextDiffCtrl.h"
2
3 namespace Upp {
4
PatchDiff()5 PatchDiff::PatchDiff()
6 {
7 Icon(DiffImg::PatchDiff());
8
9 hidden.Hide();
10
11 copyright.Hide();
12 lfile.HSizePos();
13
14 copyleft.SetLabel("Patch");
15
16 files.WhenSel = [=] { File(); };
17
18 dir1.Ctrl::Remove();
19 dir2.Ctrl::Remove();
20
21 int cy = patch_file.GetStdSize().cy;
22 int div = Zy(4);
23 files_pane.Add(target_dir.TopPos(0, cy).HSizePos());
24 files_pane.Add(patch_file.TopPos(cy + div, cy).HSizePos());
25 patch_file.SetReadOnly();
26 target_dir.SetReadOnly();
27
28 seldir.Attach(target_dir);
29 seldir.Title("Target directory");
30 selfile.Attach(patch_file);
31 selfile.Title("Patch file");
32 selfile.Types("Patch files (*.diff *.patch)\t*.diff *.patch\nAll files\t*.*");
33
34 seldir.WhenSelected = selfile.WhenSelected = [=] {
35 Open(~~patch_file, Vector<String>() << ~seldir);
36 };
37
38 files_pane.Add(failed.TopPos(2 * cy + 2 * div, cy).HSizePos());
39
40 compare.SetLabel("Patch All");
41 compare ^= [=] {
42 String msg = "Patch everything?";
43 if(failed_count)
44 msg << "&[/ (" << failed_count << " files cannot be patched)";
45 if(files.GetCount() == 0 || !PromptYesNo(msg))
46 return;
47 Progress pi("Patching", patch.GetCount());
48 for(int i = 0; i < patch.GetCount(); i++) {
49 if(pi.StepCanceled())
50 return;
51 String h = patch.GetPatchedFile(i);
52 String p = patch.GetPath(i);
53 if(!h.IsVoid()) {
54 if(IsNull(h))
55 FileDelete(p);
56 else
57 SaveFile(p, h);
58 }
59 }
60 Break(IDOK);
61 };
62
63 copyleft ^= [=] {
64 int ii = GetFileIndex();
65 if(ii < 0 || !PromptYesNo("Patch [* \1" + file_path + "\1] ?") || patched_file.IsVoid())
66 return;
67 if(IsNull(patched_file))
68 FileDelete(file_path);
69 else
70 SaveFile(file_path, patched_file);
71 list[ii].d = 4;
72 files.Set(files.GetCursor(), MakeFile(ii));
73 File();
74 };
75
76 Title("Patch");
77 }
78
Open(const char * patch_path,const Vector<String> & target_dirs0)79 bool PatchDiff::Open(const char *patch_path, const Vector<String>& target_dirs0)
80 {
81 failed_count = 0;
82 list.Clear();
83 failed.Hide();
84 ShowResult();
85 patch_file <<= Null;
86 target_dir <<= Null;
87
88 Vector<String> target_dirs;
89 for(String s : target_dirs0)
90 target_dirs.Add(UnixPath(s));
91
92 Progress pi;
93 if(!patch.Load(patch_path, pi)) {
94 Exclamation("Failed to load the patch file!");
95 return false;
96 }
97
98 patch_file <<= patch_path;
99
100 if(!patch.MatchFiles(target_dirs, pi)) {
101 Exclamation("Unable to match the directory structure!");
102 return true;
103 }
104
105 String target_dir = patch.GetTargetDir();
106
107 this->target_dir <<= target_dir;
108
109 list.Clear();
110 pi.SetText("Checking files");
111 pi.SetTotal(patch.GetCount());
112 for(int i = 0; i < patch.GetCount(); i++) {
113 if(pi.StepCanceled())
114 return false;
115 String fn = patch.GetFile(i);
116 String p = patch.GetPath(i);
117 String h = patch.GetPatchedFile(i);
118 bool pe = h.GetCount();
119 bool x = FileExists(p);
120 bool failed = h.IsVoid();
121 list.Add(MakeTuple(fn, p, p, failed ? 3 : pe && x ? 0 : pe ? 2 : 1));
122 if(failed)
123 failed_count++;
124 }
125
126 failed.Show(failed_count);
127 failed.SetInk(SRed()).SetFont(StdFont().Bold().Italic());
128 failed = String() << failed_count << " file(s) cannot be patched";
129
130 ShowResult();
131
132 if(files.GetCount())
133 files.SetCursor(0);
134
135 return true;
136 }
137
GetFileIndex() const138 int PatchDiff::GetFileIndex() const
139 {
140 int ii = files.GetCursor();
141 return ii >= 0 ? (int)files.Get(ii).data : -1;
142 }
143
File()144 void PatchDiff::File()
145 {
146 diff.Set(Null, Null);
147 String p2;
148 String op = " [PATCHED]";
149 copyleft.Disable();
150 file_path.Clear();
151 patched_file.Clear();
152 int ii = GetFileIndex();
153 if(ii >= 0) {
154 file_path = patch.GetPath(ii);
155 if(GetFileLength(file_path) < 4 * 1024 * 1024) {
156 String content = LoadFile(file_path);
157 if(list[ii].d == PATCHED_FILE) {
158 p2 = "[FILE IS PATCHED]";
159 diff.Set(content, content);
160 }
161 else {
162 patched_file = patch.GetPatchedFile(ii);
163 if(patched_file.IsVoid()) {
164 diff.Set(content, patch.GetPatch(ii));
165 p2 = "[FAILED TO APPLY THE PATCH]";
166 }
167 else {
168 diff.Set(content, patched_file);
169 p2 = file_path + " [PATCHED]";
170 copyleft.Enable();
171 }
172 }
173 }
174 }
175 lfile <<= file_path;
176 rfile <<= p2;
177 }
178
179 };