Merge lp:~mac9416/keryx/keryx-1.0 into lp:keryx/unstable

Proposed by mac9416
Status: Merged
Merged at revision: 36
Proposed branch: lp:~mac9416/keryx/keryx-1.0
Merge into: lp:keryx/unstable
Diff against target: 494 lines (+133/-148)
4 files modified
.bzrignore (+5/-5)
bin/keryx (+119/-69)
data/ui/KeryxWindow.ui (+5/-70)
keryx/keryxconfig.py (+4/-4)
To merge this branch: bzr merge lp:~mac9416/keryx/keryx-1.0
Reviewer Review Type Date Requested Status
Senthil Kumar_Webrsk (community) Approve
Keryx Admins Pending
Review via email: mp+36507@code.launchpad.net

Description of the change

"Code‽ I don't have time to code! There's hay to be bailed and cows to be milked and..."

Anyway, I made some time to code. I managed to implement the Download button and the Installed Version text. That required an additional function in Unwrapt, mind you, (merge request for that coming soon) so be sure to update both branches before testing.

I'm adding RSK as a reviewer.

To post a comment you must log in.
Revision history for this message
mac9416 (mac9416) wrote :

Bah, looks like I forgot to push the last batch of code into unstable. RSK, you'll just have to skim over old stuff. :-)

Revision history for this message
Senthil Kumar_Webrsk (webrsk-ideas) wrote :

> Bah, looks like I forgot to push the last batch of code into unstable. RSK,
> you'll just have to skim over old stuff. :-)

So do i have to take 63 revision of lp:~mac9416/keryx/unwrapt ?

Revision history for this message
mac9416 (mac9416) wrote :

> So do i have to take 63 revision of lp:~mac9416/keryx/unwrapt ?

Yes, for this revision of Keryx, you'll have to have the latest Unwrapt revision from my branch as well.

To make Keryx able to import Unwrapt, you'll have to create a link at keryx/unwrapt to the unwrapt directory in your local Unwrapt branch. If keryx/unwrapt already exists, replace it with your new link.

Revision history for this message
Senthil Kumar_Webrsk (webrsk-ideas) wrote :

When i try to manage the computer it fails to download the index files. As per the code it should proceed further but it raises more error.
Reading packing lists... 46%Traceback
IOError:Not a gzipped file

review: Needs Information
Revision history for this message
mac9416 (mac9416) wrote :

I've encountered that error too. By adding a print statement to the index file reading code in Unwrapt, I was able to see that it was a Medibuntu index file that threw the error. Opening the file with an archive app worked perfectly fine.
Even more befuddling is that the error occurs on my 64-bit Studio desktop, but not my 32-bit Lubuntu laptop. I'll test on another 32-bit machine and see what happens.

At any rate, you can disable whatever repos are causing the error and continue testing. I'll send a message to the mailing list that this needs looking into.

Revision history for this message
mac9416 (mac9416) wrote :

Hey, RSK, I'm going to go on and merge this in. If there are any serious issues, we'll iron them out later.

Revision history for this message
Senthil Kumar_Webrsk (webrsk-ideas) wrote :

Ya we can proceed merging :)

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file '.bzrignore'
--- .bzrignore 2010-08-07 03:19:39 +0000
+++ .bzrignore 2010-09-23 21:27:41 +0000
@@ -12,9 +12,9 @@
12.git/objects12.git/objects
13.git/refs13.git/refs
14.git14.git
15data/projects/amanda
16data/projects/amandasd
17data/downloads
18data/downloads
19data/keryx.conf15data/keryx.conf
20data/projects16data/projects/*
17data/downloads/*
18downloads/*
19data/profiles
20keryx/unwrapt
2121
=== modified file 'bin/keryx'
--- bin/keryx 2010-08-17 00:09:50 +0000
+++ bin/keryx 2010-09-23 21:27:41 +0000
@@ -27,30 +27,59 @@
27from gettext import gettext as _27from gettext import gettext as _
28gettext.textdomain('keryx')28gettext.textdomain('keryx')
2929
30# optional Launchpad integration30
31# this shouldn't crash if not found as it is simply used for bug reporting31### Optional Launchpad integration ###
32# This shouldn't crash if not found as it is simply used for bug reporting.
32try:33try:
33 import LaunchpadIntegration34 import LaunchpadIntegration
34 launchpad_available = True35 launchpad_available = True
35except:36except:
36 launchpad_available = False37 launchpad_available = False
3738
38# Add project root directory (enable symlink, and trunk execution).39
39PROJECT_ROOT_DIRECTORY = os.path.abspath(40### Add profile root directory (enable symlink, and trunk execution). ###
41PROFILE_ROOT_DIRECTORY = os.path.abspath(
40 os.path.dirname(os.path.dirname(os.path.realpath(sys.argv[0]))))42 os.path.dirname(os.path.dirname(os.path.realpath(sys.argv[0]))))
4143
42if (os.path.exists(os.path.join(PROJECT_ROOT_DIRECTORY, 'keryx'))44if (os.path.exists(os.path.join(PROFILE_ROOT_DIRECTORY, 'keryx'))
43 and PROJECT_ROOT_DIRECTORY not in sys.path):45 and PROFILE_ROOT_DIRECTORY not in sys.path):
44 sys.path.insert(0, PROJECT_ROOT_DIRECTORY)46 sys.path.insert(0, PROFILE_ROOT_DIRECTORY)
45 os.putenv('PYTHONPATH', PROJECT_ROOT_DIRECTORY) # for subprocesses47 os.putenv('PYTHONPATH', PROFILE_ROOT_DIRECTORY) # for subprocesses
4648
47from keryx import (49
48 AboutKeryxDialog, keryxconfig)50### Start bringing in some Keryx grooviness. ###
51from keryx import AboutKeryxDialog, keryxconfig
49from keryx.MessageDialogs import (error_dialog, info_dialog, question_dialog,52from keryx.MessageDialogs import (error_dialog, info_dialog, question_dialog,
50 warning_dialog)53 warning_dialog)
51from keryx.helpers import create_tab, create_closeable_tab, get_builder54from keryx.helpers import create_tab, create_closeable_tab, get_builder
5255
5356
57class UnsupportedOSException(Exception):
58 pass
59
60
61class ProfileExistsException(Exception):
62 pass
63
64
65def is_supported_os():
66 """If the current OS is supported, return True; else, False."""
67 return platform.system() == "Linux" and \
68 os.path.exists("/var/lib/dpkg/status")
69
70
71def get_architecture():
72 """Get the architecture of the current machine, converting to an APT-
73 friendly form.
74 """
75 arch = platform.machine()
76 if arch == "x86_64":
77 arch = "amd64"
78 elif arch =="i686":
79 arch = "i386"
80 return arch
81
82
54class KeryxWindow(gtk.Window):83class KeryxWindow(gtk.Window):
55 __gtype_name__ = "KeryxWindow"84 __gtype_name__ = "KeryxWindow"
56 85
@@ -102,12 +131,12 @@
102 else:131 else:
103 launchpad_available = False132 launchpad_available = False
104133
105 # Uncomment the following code to read in preferences at start up.134 # Load in the preferences.
106 self.config = keryxconfig.Config()135 self.config = keryxconfig.Config()
107136
108 # Code for other initialization actions should be added here.137 # Code for other initialization actions should be added here.
109 self.notebook = self._get("notebook")138 self.notebook = self._get("notebook")
110 139
111 name = self._get("add_computer_name_entry")140 name = self._get("add_computer_name_entry")
112 name.set_text(platform.node()) 141 name.set_text(platform.node())
113 142
@@ -136,12 +165,12 @@
136 165
137 166
138 def load_config(self):167 def load_config(self):
139 # Create and set the projects folder168 # Create and set the profiles folder
140 projects_chooser = self._get("projects_filechooserbutton")169 profiles_chooser = self._get("profiles_filechooserbutton")
141 path = os.path.abspath(self.config.get("projects"))170 path = os.path.abspath(self.config.get("profiles"))
142 if not os.path.exists(path):171 if not os.path.exists(path):
143 os.makedirs(path)172 os.makedirs(path)
144 projects_chooser.set_current_folder(path)173 profiles_chooser.set_current_folder(path)
145 174
146 # Create and set the downloads folder175 # Create and set the downloads folder
147 downloads_chooser = self._get("downloads_filechooserbutton")176 downloads_chooser = self._get("downloads_filechooserbutton")
@@ -160,7 +189,7 @@
160 self._get("proxy_username_entry").set_text(self.config.get("proxy_username"))189 self._get("proxy_username_entry").set_text(self.config.get("proxy_username"))
161 self._get("proxy_password_entry").set_text(self.config.get("proxy_password"))190 self._get("proxy_password_entry").set_text(self.config.get("proxy_password"))
162 191
163 for root, dirs, files in os.walk(self.config.get("projects")):192 for root, dirs, files in os.walk(self.config.get("profiles")):
164 for computer in [filename for filename in files if filename.endswith(".keryx")]:193 for computer in [filename for filename in files if filename.endswith(".keryx")]:
165 self.computers_list.append([computer[:-6], root])194 self.computers_list.append([computer[:-6], root])
166195
@@ -200,11 +229,11 @@
200 "Path": path,229 "Path": path,
201 "Client": client}230 "Client": client}
202 231
203 f = open(os.path.join(path, "apt.conf"), "rb")232 f = open(os.path.join(path, "profile.conf"), "rb")
204 lines = f.readlines() 233 lines = f.readlines()
205 f.close()234 f.close()
206 235
207 # Read apt.conf236 # Read profile.conf
208 hostname = lines[0].strip()237 hostname = lines[0].strip()
209 dist, version, codename = [line.strip() for line in lines[1].split()]238 dist, version, codename = [line.strip() for line in lines[1].split()]
210 arch = lines[2].strip()239 arch = lines[2].strip()
@@ -216,14 +245,13 @@
216 client.set_status(os.path.join(path, "status"))245 client.set_status(os.path.join(path, "status"))
217 246
218 # Set repositories247 # Set repositories
248 #TODO: Don't forget sources.list.d files.
219 f = open(os.path.join(path, "sources.list"), "rb")249 f = open(os.path.join(path, "sources.list"), "rb")
220 repos = f.readlines()250 repos = f.readlines()
221 f.close()251 f.close()
222 252
223 def valid_line(line):253 def valid_line(line):
224 """254 """Take an APT source line and only return it if it's valid."""
225 Verify a sources line
226 """
227 line = line.strip()255 line = line.strip()
228 256
229 # Line must not be empty257 # Line must not be empty
@@ -234,13 +262,17 @@
234 262
235 return line263 return line
236 264
237
238 265
239 # Parse for valid repos266 # Parse for valid repos
240 repos = [valid_line(line) for line in repos if valid_line(line)]267 repos = [valid_line(line) for line in repos if valid_line(line)]
241 268
242 client.set_repositories(repos)269 client.set_repositories(repos)
243 client.update() #TODO: reporthook270 try:
271 client.update() #TODO: reporthook
272 except IOError:
273 logging.error(_("Downloading index files failed. Loading profile " \
274 "without downloading index files."))
275 client.update(download=False)
244 276
245 277
246 for item in client.get_available_package_names():278 for item in client.get_available_package_names():
@@ -259,53 +291,52 @@
259 textbuf = self._get("package_textbuffer")291 textbuf = self._get("package_textbuffer")
260 textbuf.set_text(package["Long"])292 textbuf.set_text(package["Long"])
261293
262 #self.computer["Client"].get_package_status(294 version = self.computer["Client"].get_package_version(name)
263 #self._get("installed_label").set_text(295 if not version:
264296 version = _("None")
265297 self._get("installed_label").set_text(version)
266 #TODO: Move errors to their own function to be called easily298
299
267 def on_add_button_clicked(self, widget, data=None):300 def on_add_button_clicked(self, widget, data=None):
268 status_file = "/var/lib/dpkg/status"
269 sources_file = "/etc/apt/sources.list"
270
271 if not platform.system() == "Linux" or \
272 not os.path.exists(status_file) or \
273 not os.path.exists(sources_file): # FIXME: Not everyone has a main sources_file.
274 error_dialog(self,
275 "Sorry, you can only add Debian based Linux " \
276 "distros.\nPlease use Keryx on your offline " \
277 "machine.",
278 "Error adding computer")
279 return
280
281 name = self._get("add_computer_name_entry").get_text()301 name = self._get("add_computer_name_entry").get_text()
282 302 path = os.path.join(self.config.get("profiles"), name)
283 path = os.path.join(self.config.get("projects"), name)303
304 try:
305 self.create_profile(name, path)
306 except UnsupportedOSException:
307 self.wrong_os_dialog()
308 return
309 except ProfileExistsException:
310 self.already_managed_dialog()
311 logging.error("Computer already managed: %s" % path)
312 return
313
314 self.computers_list.append([name, path])
315 info_dialog(self,
316 "Computer added successfully!\n\nTo get started, take " \
317 "Keryx to a computer with internet access or\nyou can " \
318 "click Manage now to mark packages to download later.",
319 "Everything Went Better Than Expected")
320
321 def create_profile(self, name, path):
322 if not is_supported_os():
323 raise UnsupportedOSException
324
325 # Create the new profile's directory.
284 if os.path.exists(path):326 if os.path.exists(path):
285 error_dialog(self, 327 raise ProfileExistsException
286 "The computer appears to have already been added.\n" \
287 "\nMake sure you to use a different name for each " \
288 "computer.",
289 "Error Adding Computer")
290 logging.error("Computer already managed: %s" % path)
291 return
292
293 os.makedirs(path)328 os.makedirs(path)
329
330 # Create the .keryx config file.
294 filename = "%s.keryx" % name331 filename = "%s.keryx" % name
295 f = open(os.path.join(path, filename), "wb")332 f = open(os.path.join(path, filename), "wb")
296 f.write("%s\napt" % name)333 f.write("%s\napt" % name)
297 f.close()334 f.close()
298 335
299 self.computers_list.append([name, path])336 f = open(os.path.join(path, "profile.conf"), "wb")
300 337 f.write("%s\n%s\n%s\n%s" % (platform.uname()[1],
301 arch = platform.machine()
302 if arch == "x86_64":
303 arch = "amd64"
304
305 f = open(os.path.join(path, "apt.conf"), "wb")
306 f.write("%s\n%s\n%s\n%s" % (platform.uname()[1],
307 " ".join(platform.linux_distribution()), 338 " ".join(platform.linux_distribution()),
308 arch,339 get_architecture(),
309 platform.release()))340 platform.release()))
310 f.close()341 f.close()
311 342
@@ -318,12 +349,6 @@
318 349
319 shutil.copy("/var/lib/dpkg/status", os.path.join(path, "status"))350 shutil.copy("/var/lib/dpkg/status", os.path.join(path, "status"))
320 351
321 info_dialog(self,
322 "Computer added successfully!\n\nTo get started, take " \
323 "Keryx to a computer with internet access or\nyou can " \
324 "click Manage now to mark packages to download later.",
325 "Everything Went Better Than Expected")
326
327 def about(self, widget, data=None):352 def about(self, widget, data=None):
328 """Display the about box for keryx."""353 """Display the about box for keryx."""
329 about = AboutKeryxDialog.AboutKeryxDialog()354 about = AboutKeryxDialog.AboutKeryxDialog()
@@ -360,7 +385,7 @@
360 self._get(item).set_sensitive(s)385 self._get(item).set_sensitive(s)
361386
362 def on_preferences_changed(self, widget, data=None):387 def on_preferences_changed(self, widget, data=None):
363 self.config.set("projects", self._get("projects_filechooserbutton").get_current_folder())388 self.config.set("profiles", self._get("profiles_filechooserbutton").get_current_folder())
364 self.config.set("downloads", self._get("downloads_filechooserbutton").get_current_folder())389 self.config.set("downloads", self._get("downloads_filechooserbutton").get_current_folder())
365 390
366 self.config.set("proxy", self._get("proxy_manual_radiobutton").get_active())391 self.config.set("proxy", self._get("proxy_manual_radiobutton").get_active())
@@ -379,10 +404,35 @@
379 404
380 def on_switch_tab(self, notebook, page, page_num, data=None):405 def on_switch_tab(self, notebook, page, page_num, data=None):
381 self._get("preferences_label").set_text("Click Save to apply changes")406 self._get("preferences_label").set_text("Click Save to apply changes")
407
408 def on_download(self, widget, data=None):
409 # Get the name of the package selected (overcomplicated process).
410 liststore, treeiter = self._get("packages_treeview").get_selection().get_selected()
411 name = liststore.get_value(treeiter, 0)
412
413 # Download the package.
414 client = self.computer["Client"]
415 package = client.get_latest_binary(name)
416 client.mark_package(package)
417 client.apply_changes()
382 418
383 def _get(self, name):419 def _get(self, name):
384 return self.builder.get_object(name)420 return self.builder.get_object(name)
385421
422 ### Error dialogs ###
423
424 def wrong_os_dialog(self):
425 error_dialog(self,
426 "Sorry, you can only add Debian based Linux distros.\n" \
427 "Please use Keryx on your offline computer.",
428 "Error Adding Computer")
429
430 def already_managed_dialog(self):
431 error_dialog(self,
432 "The computer appears to have already been added.\n\n" \
433 "Make sure you to use a different name for each computer.",
434 "Error Adding Computer")
435
386if __name__ == "__main__":436if __name__ == "__main__":
387 # Support for command line options.437 # Support for command line options.
388 import optparse438 import optparse
389439
=== modified file 'data/ui/KeryxWindow.ui'
--- data/ui/KeryxWindow.ui 2010-08-17 00:09:50 +0000
+++ data/ui/KeryxWindow.ui 2010-09-23 21:27:41 +0000
@@ -70,24 +70,6 @@
70 </object>70 </object>
71 </child>71 </child>
72 <child>72 <child>
73 <object class="GtkImageMenuItem" id="imagemenuitem3">
74 <property name="label">gtk-save</property>
75 <property name="visible">True</property>
76 <property name="use_underline">True</property>
77 <property name="use_stock">True</property>
78 <accelerator key="s" signal="activate" modifiers="GDK_CONTROL_MASK"/>
79 </object>
80 </child>
81 <child>
82 <object class="GtkImageMenuItem" id="imagemenuitem4">
83 <property name="label">gtk-save-as</property>
84 <property name="visible">True</property>
85 <property name="use_underline">True</property>
86 <property name="use_stock">True</property>
87 <accelerator key="s" signal="activate" modifiers="GDK_SHIFT_MASK | GDK_CONTROL_MASK"/>
88 </object>
89 </child>
90 <child>
91 <object class="GtkSeparatorMenuItem" id="separatormenuitem1">73 <object class="GtkSeparatorMenuItem" id="separatormenuitem1">
92 <property name="visible">True</property>74 <property name="visible">True</property>
93 </object>75 </object>
@@ -115,47 +97,6 @@
115 <object class="GtkMenu" id="menu2">97 <object class="GtkMenu" id="menu2">
116 <property name="visible">True</property>98 <property name="visible">True</property>
117 <child>99 <child>
118 <object class="GtkImageMenuItem" id="imagemenuitem6">
119 <property name="label">gtk-cut</property>
120 <property name="visible">True</property>
121 <property name="use_underline">True</property>
122 <property name="use_stock">True</property>
123 <accelerator key="x" signal="activate" modifiers="GDK_CONTROL_MASK"/>
124 </object>
125 </child>
126 <child>
127 <object class="GtkImageMenuItem" id="imagemenuitem7">
128 <property name="label">gtk-copy</property>
129 <property name="visible">True</property>
130 <property name="use_underline">True</property>
131 <property name="use_stock">True</property>
132 <accelerator key="c" signal="activate" modifiers="GDK_CONTROL_MASK"/>
133 </object>
134 </child>
135 <child>
136 <object class="GtkImageMenuItem" id="imagemenuitem8">
137 <property name="label">gtk-paste</property>
138 <property name="visible">True</property>
139 <property name="use_underline">True</property>
140 <property name="use_stock">True</property>
141 <accelerator key="v" signal="activate" modifiers="GDK_CONTROL_MASK"/>
142 </object>
143 </child>
144 <child>
145 <object class="GtkImageMenuItem" id="imagemenuitem9">
146 <property name="label">gtk-delete</property>
147 <property name="visible">True</property>
148 <property name="use_underline">True</property>
149 <property name="use_stock">True</property>
150 <accelerator key="Delete" signal="activate"/>
151 </object>
152 </child>
153 <child>
154 <object class="GtkSeparatorMenuItem" id="separatormenuitem2">
155 <property name="visible">True</property>
156 </object>
157 </child>
158 <child>
159 <object class="GtkImageMenuItem" id="imagemenuitem11">100 <object class="GtkImageMenuItem" id="imagemenuitem11">
160 <property name="label">gtk-preferences</property>101 <property name="label">gtk-preferences</property>
161 <property name="visible">True</property>102 <property name="visible">True</property>
@@ -169,13 +110,6 @@
169 </object>110 </object>
170 </child>111 </child>
171 <child>112 <child>
172 <object class="GtkMenuItem" id="menuitem3">
173 <property name="visible">True</property>
174 <property name="label" translatable="yes">_View</property>
175 <property name="use_underline">True</property>
176 </object>
177 </child>
178 <child>
179 <object class="GtkMenuItem" id="menuitem4">113 <object class="GtkMenuItem" id="menuitem4">
180 <property name="visible">True</property>114 <property name="visible">True</property>
181 <property name="label" translatable="yes">_Help</property>115 <property name="label" translatable="yes">_Help</property>
@@ -675,6 +609,7 @@
675 <property name="visible">True</property>609 <property name="visible">True</property>
676 <property name="can_focus">True</property>610 <property name="can_focus">True</property>
677 <property name="receives_default">True</property>611 <property name="receives_default">True</property>
612 <signal name="clicked" handler="on_download"/>
678 <child>613 <child>
679 <object class="GtkHBox" id="hbox3">614 <object class="GtkHBox" id="hbox3">
680 <property name="visible">True</property>615 <property name="visible">True</property>
@@ -765,7 +700,7 @@
765 <object class="GtkLabel" id="label20">700 <object class="GtkLabel" id="label20">
766 <property name="visible">True</property>701 <property name="visible">True</property>
767 <property name="xalign">0</property>702 <property name="xalign">0</property>
768 <property name="label" translatable="yes">Projects:</property>703 <property name="label" translatable="yes">Profiles:</property>
769 <property name="width_chars">10</property>704 <property name="width_chars">10</property>
770 </object>705 </object>
771 <packing>706 <packing>
@@ -775,10 +710,10 @@
775 </packing>710 </packing>
776 </child>711 </child>
777 <child>712 <child>
778 <object class="GtkFileChooserButton" id="projects_filechooserbutton">713 <object class="GtkFileChooserButton" id="profiles_filechooserbutton">
779 <property name="visible">True</property>714 <property name="visible">True</property>
715 <property name="show_hidden">True</property>
780 <property name="action">select-folder</property>716 <property name="action">select-folder</property>
781 <property name="show_hidden">True</property>
782 </object>717 </object>
783 <packing>718 <packing>
784 <property name="expand">False</property>719 <property name="expand">False</property>
@@ -810,8 +745,8 @@
810 <child>745 <child>
811 <object class="GtkFileChooserButton" id="downloads_filechooserbutton">746 <object class="GtkFileChooserButton" id="downloads_filechooserbutton">
812 <property name="visible">True</property>747 <property name="visible">True</property>
748 <property name="show_hidden">True</property>
813 <property name="action">select-folder</property>749 <property name="action">select-folder</property>
814 <property name="show_hidden">True</property>
815 </object>750 </object>
816 <packing>751 <packing>
817 <property name="expand">False</property>752 <property name="expand">False</property>
818753
=== modified file 'keryx/keryxconfig.py'
--- keryx/keryxconfig.py 2010-08-05 18:55:48 +0000
+++ keryx/keryxconfig.py 2010-09-23 21:27:41 +0000
@@ -73,7 +73,7 @@
73class Config:73class Config:
74 section = "keryx"74 section = "keryx"
75 defaults = [("data", get_data_path()), 75 defaults = [("data", get_data_path()),
76 ("projects", os.path.join(get_data_path(), "projects")), 76 ("profiles", os.path.join(get_data_path(), "profiles")),
77 ("downloads", os.path.join(get_data_path(), "downloads")),77 ("downloads", os.path.join(get_data_path(), "downloads")),
78 ("proxy", "False"),78 ("proxy", "False"),
79 ("proxy_url", "http://localhost"),79 ("proxy_url", "http://localhost"),
@@ -92,10 +92,10 @@
92 self._set_defaults()92 self._set_defaults()
93 self.config_file = config_path93 self.config_file = config_path
94 94
95 projects_path = os.path.join(get_data_path(), "projects")95 profiles_path = os.path.join(get_data_path(), "profiles")
96 96
97 if not os.path.exists(projects_path):97 if not os.path.exists(profiles_path):
98 os.mkdir(projects_path) 98 os.mkdir(profiles_path)
99 99
100 def get_filename(self):100 def get_filename(self):
101 return self.config_file101 return self.config_file
102102
=== removed symlink 'keryx/unwrapt'
=== target was u'/home/chris/projects/unwrapt/unwrapt/'

Subscribers

People subscribed via source and target branches

to all changes: