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 };