xref: /haiku/src/bin/checkitout.cpp (revision a5330a8e41fab3b82f43d3e0d454f7abfa7b9174)
1 /*
2  * Copyright 2007-2009 Haiku Inc. All rights reserved.
3  * Distributed under the terms of the MIT License.
4  *
5  * Authors:
6  *		François Revol, revol@free.fr
7  *		Jonas Sundström, jonas@kirilla.com
8  */
9 
10 /*
11  * CheckItOut: wraps SCM URL mime types around command line apps
12  * to check out sources in a user-friendly fashion.
13  */
14 #define DEBUG 1
15 
16 #include <ctype.h>
17 #include <stdio.h>
18 #include <unistd.h>
19 
20 #include <Alert.h>
21 #include <Debug.h>
22 #include <FilePanel.h>
23 #include <NodeInfo.h>
24 #include <Path.h>
25 #include <Roster.h>
26 #include <String.h>
27 #include <Url.h>
28 
29 #include "checkitout.h"
30 
31 
32 const char* kAppSig = "application/x-vnd.Haiku-checkitout";
33 const char* kTrackerSig = "application/x-vnd.Be-TRAK";
34 #if __HAIKU__
35 const char* kTerminalSig = "application/x-vnd.Haiku-Terminal";
36 #else
37 const char* kTerminalSig = "application/x-vnd.Be-SHEL";
38 #endif
39 
CheckItOut()40 CheckItOut::CheckItOut() : BApplication(kAppSig)
41 {
42 }
43 
44 
~CheckItOut()45 CheckItOut::~CheckItOut()
46 {
47 }
48 
49 
50 status_t
_Warn(const char * url)51 CheckItOut::_Warn(const char* url)
52 {
53 	BString message("An application has requested the system to open the "
54 		"following url: \n");
55 	message << "\n" << url << "\n\n";
56 	message << "This type of URL has a potential security risk.\n";
57 	message << "Proceed anyway?";
58 	BAlert* alert = new BAlert("Warning", message.String(), "Proceed", "Stop", NULL,
59 		B_WIDTH_AS_USUAL, B_WARNING_ALERT);
60 	alert->SetShortcut(1, B_ESCAPE);
61 	int32 button;
62 	button = alert->Go();
63 	if (button == 0)
64 		return B_OK;
65 
66 	return B_ERROR;
67 }
68 
69 
70 status_t
_FilePanel(uint32 nodeFlavors,BString & name)71 CheckItOut::_FilePanel(uint32 nodeFlavors, BString &name)
72 {
73 	BFilePanel *panel = new BFilePanel(B_SAVE_PANEL);
74 	/*
75 			BMessenger* target = NULL, const entry_ref* directory = NULL,
76 			uint32 nodeFlavors = 0, bool allowMultipleSelection = true,
77 			BMessage* message = NULL, BRefFilter* refFilter = NULL,
78 			bool modal = false, bool hideWhenDone = true);
79 	*/
80 	panel->Window()->SetTitle("Check It Out to...");
81 	panel->SetSaveText(name.String());
82 	panel->Show();
83 	return B_OK;
84 }
85 
86 
87 void
RefsReceived(BMessage * msg)88 CheckItOut::RefsReceived(BMessage* msg)
89 {
90 }
91 
92 
93 void
MessageReceived(BMessage * msg)94 CheckItOut::MessageReceived(BMessage* msg)
95 {
96 			msg->PrintToStream();
97 	switch (msg->what) {
98 		case B_SAVE_REQUESTED:
99 		{
100 			entry_ref ref;
101 			BString name;
102 			msg->FindRef("directory", &ref);
103 			msg->FindString("name", &name);
104 			_DoCheckItOut(&ref, name.String());
105 			break;
106 		}
107 		case B_CANCEL:
108 			Quit();
109 			break;
110 	}
111 }
112 
113 
114 void
ArgvReceived(int32 argc,char ** argv)115 CheckItOut::ArgvReceived(int32 argc, char** argv)
116 {
117 	if (argc <= 1) {
118 		exit(1);
119 		return;
120 	}
121 
122 	BUrl url(argv[1]);
123 	fUrlString = url;
124 
125 	BString full = BUrl(url).SetProtocol(BString()).UrlString();
126 	BString proto = url.Protocol();
127 	BString host = url.Host();
128 	BString port = BString() << url.Port();
129 	BString user = url.UserInfo();
130 	BString pass = url.Password();
131 	BString path = url.Path();
132 
133 	if (!url.IsValid()) {
134 		fprintf(stderr, "malformed url: '%s'\n", url.UrlString().String());
135 		return;
136 	}
137 
138 	// XXX: debug
139 	PRINT(("PROTO='%s'\n", proto.String()));
140 	PRINT(("HOST='%s'\n", host.String()));
141 	PRINT(("PORT='%s'\n", port.String()));
142 	PRINT(("USER='%s'\n", user.String()));
143 	PRINT(("PASS='%s'\n", pass.String()));
144 	PRINT(("PATH='%s'\n", path.String()));
145 
146 	BString leaf(url.Path());
147 	if (leaf.FindLast('/') > -1)
148 		leaf.Remove(0, leaf.FindLast('/') + 1);
149 	PRINT(("leaf %s\n", leaf.String()));
150 	_FilePanel(B_DIRECTORY_NODE, leaf);
151 
152 }
153 
154 status_t
_DoCheckItOut(entry_ref * ref,const char * name)155 CheckItOut::_DoCheckItOut(entry_ref *ref, const char *name)
156 {
157 	const char* failc = " || read -p 'Press any key'";
158 	const char* pausec = " ; read -p 'Press any key'";
159 	char* args[] = { (char *)"/bin/sh", (char *)"-c", NULL, NULL};
160 
161 	BUrl url(fUrlString);
162 	BString full = BUrl(url).SetProtocol(BString()).UrlString();
163 	BString proto = url.Protocol();
164 	BString host = url.Host();
165 	BString port = BString() << url.Port();
166 	BString user = url.UserInfo();
167 	BString pass = url.Password();
168 	BString path = url.Path();
169 	PRINT(("url %s\n", url.UrlString().String()));
170 	BPath refPath(ref);
171 
172 	if (proto == "git") {
173 		BString cmd("git clone ");
174 		cmd << url;
175 		cmd << " '" << refPath.Path() << "/" << name << "'";
176 		PRINT(("CMD='%s'\n", cmd.String()));
177 		cmd << " && open '" << refPath.Path() << "/" << name << "'";
178 		cmd << failc;
179 		PRINT(("CMD='%s'\n", cmd.String()));
180 		args[2] = (char*)cmd.String();
181 		be_roster->Launch(kTerminalSig, 3, args);
182 		return B_OK;
183 	}
184 	if (proto == "rsync") {
185 		BString cmd("rsync ");
186 		cmd << url;
187 		cmd << " '" << refPath.Path() << "/" << name << "'";
188 		PRINT(("CMD='%s'\n", cmd.String()));
189 		cmd << " && open '" << refPath.Path() << "/" << name << "'";
190 		cmd << failc;
191 		PRINT(("CMD='%s'\n", cmd.String()));
192 		args[2] = (char*)cmd.String();
193 		be_roster->Launch(kTerminalSig, 3, args);
194 		return B_OK;
195 	}
196 	if (proto == "svn" || proto == "svn+ssh") {
197 		BString cmd("svn checkout ");
198 		cmd << url;
199 		cmd << " '" << refPath.Path() << "/" << name << "'";
200 		PRINT(("CMD='%s'\n", cmd.String()));
201 		cmd << " && open '" << refPath.Path() << "/" << name << "'";
202 		cmd << failc;
203 		PRINT(("CMD='%s'\n", cmd.String()));
204 		args[2] = (char*)cmd.String();
205 		be_roster->Launch(kTerminalSig, 3, args);
206 		return B_OK;
207 	}
208 	return B_ERROR;
209 }
210 
211 
212 status_t
_DecodeUrlString(BString & string)213 CheckItOut::_DecodeUrlString(BString& string)
214 {
215 	// TODO: check for %00 and bail out!
216 	int32 length = string.Length();
217 	int i;
218 	for (i = 0; string[i] && i < length - 2; i++) {
219 		if (string[i] == '%' && isxdigit(string[i+1])
220 			&& isxdigit(string[i+2])) {
221 			int c;
222 			sscanf(string.String() + i + 1, "%02x", &c);
223 			string.Remove(i, 3);
224 			string.Insert((char)c, 1, i);
225 			length -= 2;
226 		}
227 	}
228 
229 	return B_OK;
230 }
231 
232 
233 void
ReadyToRun(void)234 CheckItOut::ReadyToRun(void)
235 {
236 	//Quit();
237 }
238 
239 
240 // #pragma mark
241 
242 
main(int argc,char ** argv)243 int main(int argc, char** argv)
244 {
245 	CheckItOut app;
246 	if (be_app)
247 		app.Run();
248 	return 0;
249 }
250 
251