##// END OF EJS Templates
Fixes in MANIFEST.in and ipcontroller.py...
Brian Granger -
Show More
@@ -1,366 +1,369 b''
1 #!/usr/bin/env python
1 #!/usr/bin/env python
2 # encoding: utf-8
2 # encoding: utf-8
3
3
4 """The IPython controller."""
4 """The IPython controller."""
5
5
6 __docformat__ = "restructuredtext en"
6 __docformat__ = "restructuredtext en"
7
7
8 #-------------------------------------------------------------------------------
8 #-------------------------------------------------------------------------------
9 # Copyright (C) 2008 The IPython Development Team
9 # Copyright (C) 2008 The IPython Development Team
10 #
10 #
11 # Distributed under the terms of the BSD License. The full license is in
11 # Distributed under the terms of the BSD License. The full license is in
12 # the file COPYING, distributed as part of this software.
12 # the file COPYING, distributed as part of this software.
13 #-------------------------------------------------------------------------------
13 #-------------------------------------------------------------------------------
14
14
15 #-------------------------------------------------------------------------------
15 #-------------------------------------------------------------------------------
16 # Imports
16 # Imports
17 #-------------------------------------------------------------------------------
17 #-------------------------------------------------------------------------------
18
18
19 # Python looks for an empty string at the beginning of sys.path to enable
19 # Python looks for an empty string at the beginning of sys.path to enable
20 # importing from the cwd.
20 # importing from the cwd.
21 import sys
21 import sys
22 sys.path.insert(0, '')
22 sys.path.insert(0, '')
23
23
24 import sys, time, os
24 import sys, time, os
25 from optparse import OptionParser
25 from optparse import OptionParser
26
26
27 from twisted.application import internet, service
27 from twisted.application import internet, service
28 from twisted.internet import reactor, error, defer
28 from twisted.internet import reactor, error, defer
29 from twisted.python import log
29 from twisted.python import log
30
30
31 from IPython.kernel.fcutil import Tub, UnauthenticatedTub, have_crypto
31 from IPython.kernel.fcutil import Tub, UnauthenticatedTub, have_crypto
32
32
33 # from IPython.tools import growl
33 # from IPython.tools import growl
34 # growl.start("IPython1 Controller")
34 # growl.start("IPython1 Controller")
35
35
36 from IPython.kernel.error import SecurityError
36 from IPython.kernel.error import SecurityError
37 from IPython.kernel import controllerservice
37 from IPython.kernel import controllerservice
38 from IPython.kernel.fcutil import check_furl_file_security
38 from IPython.kernel.fcutil import check_furl_file_security
39
39
40 from IPython.kernel.config import config_manager as kernel_config_manager
40 from IPython.kernel.config import config_manager as kernel_config_manager
41 from IPython.config.cutils import import_item
41 from IPython.config.cutils import import_item
42
42
43
43
44 #-------------------------------------------------------------------------------
44 #-------------------------------------------------------------------------------
45 # Code
45 # Code
46 #-------------------------------------------------------------------------------
46 #-------------------------------------------------------------------------------
47
47
48 def make_tub(ip, port, secure, cert_file):
48 def make_tub(ip, port, secure, cert_file):
49 """
49 """
50 Create a listening tub given an ip, port, and cert_file location.
50 Create a listening tub given an ip, port, and cert_file location.
51
51
52 :Parameters:
52 :Parameters:
53 ip : str
53 ip : str
54 The ip address that the tub should listen on. Empty means all
54 The ip address that the tub should listen on. Empty means all
55 port : int
55 port : int
56 The port that the tub should listen on. A value of 0 means
56 The port that the tub should listen on. A value of 0 means
57 pick a random port
57 pick a random port
58 secure: boolean
58 secure: boolean
59 Will the connection be secure (in the foolscap sense)
59 Will the connection be secure (in the foolscap sense)
60 cert_file:
60 cert_file:
61 A filename of a file to be used for theSSL certificate
61 A filename of a file to be used for theSSL certificate
62 """
62 """
63 if secure:
63 if secure:
64 if have_crypto:
64 if have_crypto:
65 tub = Tub(certFile=cert_file)
65 tub = Tub(certFile=cert_file)
66 else:
66 else:
67 raise SecurityError("OpenSSL is not available, so we can't run in secure mode, aborting")
67 raise SecurityError("""
68 OpenSSL/pyOpenSSL is not available, so we can't run in secure mode.
69 Try running without security using 'ipcontroller -xy'.
70 """)
68 else:
71 else:
69 tub = UnauthenticatedTub()
72 tub = UnauthenticatedTub()
70
73
71 # Set the strport based on the ip and port and start listening
74 # Set the strport based on the ip and port and start listening
72 if ip == '':
75 if ip == '':
73 strport = "tcp:%i" % port
76 strport = "tcp:%i" % port
74 else:
77 else:
75 strport = "tcp:%i:interface=%s" % (port, ip)
78 strport = "tcp:%i:interface=%s" % (port, ip)
76 listener = tub.listenOn(strport)
79 listener = tub.listenOn(strport)
77
80
78 return tub, listener
81 return tub, listener
79
82
80 def make_client_service(controller_service, config):
83 def make_client_service(controller_service, config):
81 """
84 """
82 Create a service that will listen for clients.
85 Create a service that will listen for clients.
83
86
84 This service is simply a `foolscap.Tub` instance that has a set of Referenceables
87 This service is simply a `foolscap.Tub` instance that has a set of Referenceables
85 registered with it.
88 registered with it.
86 """
89 """
87
90
88 # Now create the foolscap tub
91 # Now create the foolscap tub
89 ip = config['controller']['client_tub']['ip']
92 ip = config['controller']['client_tub']['ip']
90 port = config['controller']['client_tub'].as_int('port')
93 port = config['controller']['client_tub'].as_int('port')
91 location = config['controller']['client_tub']['location']
94 location = config['controller']['client_tub']['location']
92 secure = config['controller']['client_tub']['secure']
95 secure = config['controller']['client_tub']['secure']
93 cert_file = config['controller']['client_tub']['cert_file']
96 cert_file = config['controller']['client_tub']['cert_file']
94 client_tub, client_listener = make_tub(ip, port, secure, cert_file)
97 client_tub, client_listener = make_tub(ip, port, secure, cert_file)
95
98
96 # Set the location in the trivial case of localhost
99 # Set the location in the trivial case of localhost
97 if ip == 'localhost' or ip == '127.0.0.1':
100 if ip == 'localhost' or ip == '127.0.0.1':
98 location = "127.0.0.1"
101 location = "127.0.0.1"
99
102
100 if not secure:
103 if not secure:
101 log.msg("WARNING: you are running the controller with no client security")
104 log.msg("WARNING: you are running the controller with no client security")
102
105
103 def set_location_and_register():
106 def set_location_and_register():
104 """Set the location for the tub and return a deferred."""
107 """Set the location for the tub and return a deferred."""
105
108
106 def register(empty, ref, furl_file):
109 def register(empty, ref, furl_file):
107 client_tub.registerReference(ref, furlFile=furl_file)
110 client_tub.registerReference(ref, furlFile=furl_file)
108
111
109 if location == '':
112 if location == '':
110 d = client_tub.setLocationAutomatically()
113 d = client_tub.setLocationAutomatically()
111 else:
114 else:
112 d = defer.maybeDeferred(client_tub.setLocation, "%s:%i" % (location, client_listener.getPortnum()))
115 d = defer.maybeDeferred(client_tub.setLocation, "%s:%i" % (location, client_listener.getPortnum()))
113
116
114 for ciname, ci in config['controller']['controller_interfaces'].iteritems():
117 for ciname, ci in config['controller']['controller_interfaces'].iteritems():
115 log.msg("Adapting Controller to interface: %s" % ciname)
118 log.msg("Adapting Controller to interface: %s" % ciname)
116 furl_file = ci['furl_file']
119 furl_file = ci['furl_file']
117 log.msg("Saving furl for interface [%s] to file: %s" % (ciname, furl_file))
120 log.msg("Saving furl for interface [%s] to file: %s" % (ciname, furl_file))
118 check_furl_file_security(furl_file, secure)
121 check_furl_file_security(furl_file, secure)
119 adapted_controller = import_item(ci['controller_interface'])(controller_service)
122 adapted_controller = import_item(ci['controller_interface'])(controller_service)
120 d.addCallback(register, import_item(ci['fc_interface'])(adapted_controller),
123 d.addCallback(register, import_item(ci['fc_interface'])(adapted_controller),
121 furl_file=ci['furl_file'])
124 furl_file=ci['furl_file'])
122
125
123 reactor.callWhenRunning(set_location_and_register)
126 reactor.callWhenRunning(set_location_and_register)
124 return client_tub
127 return client_tub
125
128
126
129
127 def make_engine_service(controller_service, config):
130 def make_engine_service(controller_service, config):
128 """
131 """
129 Create a service that will listen for engines.
132 Create a service that will listen for engines.
130
133
131 This service is simply a `foolscap.Tub` instance that has a set of Referenceables
134 This service is simply a `foolscap.Tub` instance that has a set of Referenceables
132 registered with it.
135 registered with it.
133 """
136 """
134
137
135 # Now create the foolscap tub
138 # Now create the foolscap tub
136 ip = config['controller']['engine_tub']['ip']
139 ip = config['controller']['engine_tub']['ip']
137 port = config['controller']['engine_tub'].as_int('port')
140 port = config['controller']['engine_tub'].as_int('port')
138 location = config['controller']['engine_tub']['location']
141 location = config['controller']['engine_tub']['location']
139 secure = config['controller']['engine_tub']['secure']
142 secure = config['controller']['engine_tub']['secure']
140 cert_file = config['controller']['engine_tub']['cert_file']
143 cert_file = config['controller']['engine_tub']['cert_file']
141 engine_tub, engine_listener = make_tub(ip, port, secure, cert_file)
144 engine_tub, engine_listener = make_tub(ip, port, secure, cert_file)
142
145
143 # Set the location in the trivial case of localhost
146 # Set the location in the trivial case of localhost
144 if ip == 'localhost' or ip == '127.0.0.1':
147 if ip == 'localhost' or ip == '127.0.0.1':
145 location = "127.0.0.1"
148 location = "127.0.0.1"
146
149
147 if not secure:
150 if not secure:
148 log.msg("WARNING: you are running the controller with no engine security")
151 log.msg("WARNING: you are running the controller with no engine security")
149
152
150 def set_location_and_register():
153 def set_location_and_register():
151 """Set the location for the tub and return a deferred."""
154 """Set the location for the tub and return a deferred."""
152
155
153 def register(empty, ref, furl_file):
156 def register(empty, ref, furl_file):
154 engine_tub.registerReference(ref, furlFile=furl_file)
157 engine_tub.registerReference(ref, furlFile=furl_file)
155
158
156 if location == '':
159 if location == '':
157 d = engine_tub.setLocationAutomatically()
160 d = engine_tub.setLocationAutomatically()
158 else:
161 else:
159 d = defer.maybeDeferred(engine_tub.setLocation, "%s:%i" % (location, engine_listener.getPortnum()))
162 d = defer.maybeDeferred(engine_tub.setLocation, "%s:%i" % (location, engine_listener.getPortnum()))
160
163
161 furl_file = config['controller']['engine_furl_file']
164 furl_file = config['controller']['engine_furl_file']
162 engine_fc_interface = import_item(config['controller']['engine_fc_interface'])
165 engine_fc_interface = import_item(config['controller']['engine_fc_interface'])
163 log.msg("Saving furl for the engine to file: %s" % furl_file)
166 log.msg("Saving furl for the engine to file: %s" % furl_file)
164 check_furl_file_security(furl_file, secure)
167 check_furl_file_security(furl_file, secure)
165 fc_controller = engine_fc_interface(controller_service)
168 fc_controller = engine_fc_interface(controller_service)
166 d.addCallback(register, fc_controller, furl_file=furl_file)
169 d.addCallback(register, fc_controller, furl_file=furl_file)
167
170
168 reactor.callWhenRunning(set_location_and_register)
171 reactor.callWhenRunning(set_location_and_register)
169 return engine_tub
172 return engine_tub
170
173
171 def start_controller():
174 def start_controller():
172 """
175 """
173 Start the controller by creating the service hierarchy and starting the reactor.
176 Start the controller by creating the service hierarchy and starting the reactor.
174
177
175 This method does the following:
178 This method does the following:
176
179
177 * It starts the controller logging
180 * It starts the controller logging
178 * In execute an import statement for the controller
181 * In execute an import statement for the controller
179 * It creates 2 `foolscap.Tub` instances for the client and the engines
182 * It creates 2 `foolscap.Tub` instances for the client and the engines
180 and registers `foolscap.Referenceables` with the tubs to expose the
183 and registers `foolscap.Referenceables` with the tubs to expose the
181 controller to engines and clients.
184 controller to engines and clients.
182 """
185 """
183 config = kernel_config_manager.get_config_obj()
186 config = kernel_config_manager.get_config_obj()
184
187
185 # Start logging
188 # Start logging
186 logfile = config['controller']['logfile']
189 logfile = config['controller']['logfile']
187 if logfile:
190 if logfile:
188 logfile = logfile + str(os.getpid()) + '.log'
191 logfile = logfile + str(os.getpid()) + '.log'
189 try:
192 try:
190 openLogFile = open(logfile, 'w')
193 openLogFile = open(logfile, 'w')
191 except:
194 except:
192 openLogFile = sys.stdout
195 openLogFile = sys.stdout
193 else:
196 else:
194 openLogFile = sys.stdout
197 openLogFile = sys.stdout
195 log.startLogging(openLogFile)
198 log.startLogging(openLogFile)
196
199
197 # Execute any user defined import statements
200 # Execute any user defined import statements
198 cis = config['controller']['import_statement']
201 cis = config['controller']['import_statement']
199 if cis:
202 if cis:
200 try:
203 try:
201 exec cis in globals(), locals()
204 exec cis in globals(), locals()
202 except:
205 except:
203 log.msg("Error running import_statement: %s" % cis)
206 log.msg("Error running import_statement: %s" % cis)
204
207
205 # Create the service hierarchy
208 # Create the service hierarchy
206 main_service = service.MultiService()
209 main_service = service.MultiService()
207 # The controller service
210 # The controller service
208 controller_service = controllerservice.ControllerService()
211 controller_service = controllerservice.ControllerService()
209 controller_service.setServiceParent(main_service)
212 controller_service.setServiceParent(main_service)
210 # The client tub and all its refereceables
213 # The client tub and all its refereceables
211 client_service = make_client_service(controller_service, config)
214 client_service = make_client_service(controller_service, config)
212 client_service.setServiceParent(main_service)
215 client_service.setServiceParent(main_service)
213 # The engine tub
216 # The engine tub
214 engine_service = make_engine_service(controller_service, config)
217 engine_service = make_engine_service(controller_service, config)
215 engine_service.setServiceParent(main_service)
218 engine_service.setServiceParent(main_service)
216 # Start the controller service and set things running
219 # Start the controller service and set things running
217 main_service.startService()
220 main_service.startService()
218 reactor.run()
221 reactor.run()
219
222
220 def init_config():
223 def init_config():
221 """
224 """
222 Initialize the configuration using default and command line options.
225 Initialize the configuration using default and command line options.
223 """
226 """
224
227
225 parser = OptionParser()
228 parser = OptionParser()
226
229
227 # Client related options
230 # Client related options
228 parser.add_option(
231 parser.add_option(
229 "--client-ip",
232 "--client-ip",
230 type="string",
233 type="string",
231 dest="client_ip",
234 dest="client_ip",
232 help="the IP address or hostname the controller will listen on for client connections"
235 help="the IP address or hostname the controller will listen on for client connections"
233 )
236 )
234 parser.add_option(
237 parser.add_option(
235 "--client-port",
238 "--client-port",
236 type="int",
239 type="int",
237 dest="client_port",
240 dest="client_port",
238 help="the port the controller will listen on for client connections"
241 help="the port the controller will listen on for client connections"
239 )
242 )
240 parser.add_option(
243 parser.add_option(
241 '--client-location',
244 '--client-location',
242 type="string",
245 type="string",
243 dest="client_location",
246 dest="client_location",
244 help="hostname or ip for clients to connect to"
247 help="hostname or ip for clients to connect to"
245 )
248 )
246 parser.add_option(
249 parser.add_option(
247 "-x",
250 "-x",
248 action="store_false",
251 action="store_false",
249 dest="client_secure",
252 dest="client_secure",
250 help="turn off all client security"
253 help="turn off all client security"
251 )
254 )
252 parser.add_option(
255 parser.add_option(
253 '--client-cert-file',
256 '--client-cert-file',
254 type="string",
257 type="string",
255 dest="client_cert_file",
258 dest="client_cert_file",
256 help="file to store the client SSL certificate"
259 help="file to store the client SSL certificate"
257 )
260 )
258 parser.add_option(
261 parser.add_option(
259 '--task-furl-file',
262 '--task-furl-file',
260 type="string",
263 type="string",
261 dest="task_furl_file",
264 dest="task_furl_file",
262 help="file to store the FURL for task clients to connect with"
265 help="file to store the FURL for task clients to connect with"
263 )
266 )
264 parser.add_option(
267 parser.add_option(
265 '--multiengine-furl-file',
268 '--multiengine-furl-file',
266 type="string",
269 type="string",
267 dest="multiengine_furl_file",
270 dest="multiengine_furl_file",
268 help="file to store the FURL for multiengine clients to connect with"
271 help="file to store the FURL for multiengine clients to connect with"
269 )
272 )
270 # Engine related options
273 # Engine related options
271 parser.add_option(
274 parser.add_option(
272 "--engine-ip",
275 "--engine-ip",
273 type="string",
276 type="string",
274 dest="engine_ip",
277 dest="engine_ip",
275 help="the IP address or hostname the controller will listen on for engine connections"
278 help="the IP address or hostname the controller will listen on for engine connections"
276 )
279 )
277 parser.add_option(
280 parser.add_option(
278 "--engine-port",
281 "--engine-port",
279 type="int",
282 type="int",
280 dest="engine_port",
283 dest="engine_port",
281 help="the port the controller will listen on for engine connections"
284 help="the port the controller will listen on for engine connections"
282 )
285 )
283 parser.add_option(
286 parser.add_option(
284 '--engine-location',
287 '--engine-location',
285 type="string",
288 type="string",
286 dest="engine_location",
289 dest="engine_location",
287 help="hostname or ip for engines to connect to"
290 help="hostname or ip for engines to connect to"
288 )
291 )
289 parser.add_option(
292 parser.add_option(
290 "-y",
293 "-y",
291 action="store_false",
294 action="store_false",
292 dest="engine_secure",
295 dest="engine_secure",
293 help="turn off all engine security"
296 help="turn off all engine security"
294 )
297 )
295 parser.add_option(
298 parser.add_option(
296 '--engine-cert-file',
299 '--engine-cert-file',
297 type="string",
300 type="string",
298 dest="engine_cert_file",
301 dest="engine_cert_file",
299 help="file to store the engine SSL certificate"
302 help="file to store the engine SSL certificate"
300 )
303 )
301 parser.add_option(
304 parser.add_option(
302 '--engine-furl-file',
305 '--engine-furl-file',
303 type="string",
306 type="string",
304 dest="engine_furl_file",
307 dest="engine_furl_file",
305 help="file to store the FURL for engines to connect with"
308 help="file to store the FURL for engines to connect with"
306 )
309 )
307 parser.add_option(
310 parser.add_option(
308 "-l", "--logfile",
311 "-l", "--logfile",
309 type="string",
312 type="string",
310 dest="logfile",
313 dest="logfile",
311 help="log file name (default is stdout)"
314 help="log file name (default is stdout)"
312 )
315 )
313 parser.add_option(
316 parser.add_option(
314 "--ipythondir",
317 "--ipythondir",
315 type="string",
318 type="string",
316 dest="ipythondir",
319 dest="ipythondir",
317 help="look for config files and profiles in this directory"
320 help="look for config files and profiles in this directory"
318 )
321 )
319
322
320 (options, args) = parser.parse_args()
323 (options, args) = parser.parse_args()
321
324
322 kernel_config_manager.update_config_obj_from_default_file(options.ipythondir)
325 kernel_config_manager.update_config_obj_from_default_file(options.ipythondir)
323 config = kernel_config_manager.get_config_obj()
326 config = kernel_config_manager.get_config_obj()
324
327
325 # Update with command line options
328 # Update with command line options
326 if options.client_ip is not None:
329 if options.client_ip is not None:
327 config['controller']['client_tub']['ip'] = options.client_ip
330 config['controller']['client_tub']['ip'] = options.client_ip
328 if options.client_port is not None:
331 if options.client_port is not None:
329 config['controller']['client_tub']['port'] = options.client_port
332 config['controller']['client_tub']['port'] = options.client_port
330 if options.client_location is not None:
333 if options.client_location is not None:
331 config['controller']['client_tub']['location'] = options.client_location
334 config['controller']['client_tub']['location'] = options.client_location
332 if options.client_secure is not None:
335 if options.client_secure is not None:
333 config['controller']['client_tub']['secure'] = options.client_secure
336 config['controller']['client_tub']['secure'] = options.client_secure
334 if options.client_cert_file is not None:
337 if options.client_cert_file is not None:
335 config['controller']['client_tub']['cert_file'] = options.client_cert_file
338 config['controller']['client_tub']['cert_file'] = options.client_cert_file
336 if options.task_furl_file is not None:
339 if options.task_furl_file is not None:
337 config['controller']['controller_interfaces']['task']['furl_file'] = options.task_furl_file
340 config['controller']['controller_interfaces']['task']['furl_file'] = options.task_furl_file
338 if options.multiengine_furl_file is not None:
341 if options.multiengine_furl_file is not None:
339 config['controller']['controller_interfaces']['multiengine']['furl_file'] = options.multiengine_furl_file
342 config['controller']['controller_interfaces']['multiengine']['furl_file'] = options.multiengine_furl_file
340 if options.engine_ip is not None:
343 if options.engine_ip is not None:
341 config['controller']['engine_tub']['ip'] = options.engine_ip
344 config['controller']['engine_tub']['ip'] = options.engine_ip
342 if options.engine_port is not None:
345 if options.engine_port is not None:
343 config['controller']['engine_tub']['port'] = options.engine_port
346 config['controller']['engine_tub']['port'] = options.engine_port
344 if options.engine_location is not None:
347 if options.engine_location is not None:
345 config['controller']['engine_tub']['location'] = options.engine_location
348 config['controller']['engine_tub']['location'] = options.engine_location
346 if options.engine_secure is not None:
349 if options.engine_secure is not None:
347 config['controller']['engine_tub']['secure'] = options.engine_secure
350 config['controller']['engine_tub']['secure'] = options.engine_secure
348 if options.engine_cert_file is not None:
351 if options.engine_cert_file is not None:
349 config['controller']['engine_tub']['cert_file'] = options.engine_cert_file
352 config['controller']['engine_tub']['cert_file'] = options.engine_cert_file
350 if options.engine_furl_file is not None:
353 if options.engine_furl_file is not None:
351 config['controller']['engine_furl_file'] = options.engine_furl_file
354 config['controller']['engine_furl_file'] = options.engine_furl_file
352
355
353 if options.logfile is not None:
356 if options.logfile is not None:
354 config['controller']['logfile'] = options.logfile
357 config['controller']['logfile'] = options.logfile
355
358
356 kernel_config_manager.update_config_obj(config)
359 kernel_config_manager.update_config_obj(config)
357
360
358 def main():
361 def main():
359 """
362 """
360 After creating the configuration information, start the controller.
363 After creating the configuration information, start the controller.
361 """
364 """
362 init_config()
365 init_config()
363 start_controller()
366 start_controller()
364
367
365 if __name__ == "__main__":
368 if __name__ == "__main__":
366 main()
369 main()
@@ -1,33 +1,32 b''
1 include README_Windows.txt
2 include win32_manual_post_install.py
3 include ipython.py
1 include ipython.py
4 include setupbase.py
2 include setupbase.py
3 include setupegg.py
5
4
6 graft scripts
5 graft scripts
7
6
8 graft setupext
7 graft setupext
9
8
10 graft IPython/UserConfig
9 graft IPython/UserConfig
11
10
12 graft IPython/kernel
11 graft IPython/kernel
13 graft IPython/config
12 graft IPython/config
14 graft IPython/testing
13 graft IPython/testing
15 graft IPython/tools
14 graft IPython/tools
16
15
17 recursive-include IPython/Extensions igrid_help*
16 recursive-include IPython/Extensions igrid_help*
18
17
19 graft docs
18 graft docs
20 exclude docs/\#*
19 exclude docs/\#*
21 exclude docs/man/*.1
20 exclude docs/man/*.1
22
21
23 # docs subdirs we want to skip
22 # docs subdirs we want to skip
24 prune docs/attic
23 prune docs/attic
25 prune docs/build
24 prune docs/build
26
25
27 global-exclude *~
26 global-exclude *~
28 global-exclude *.flc
27 global-exclude *.flc
29 global-exclude *.pyc
28 global-exclude *.pyc
30 global-exclude .dircopy.log
29 global-exclude .dircopy.log
31 global-exclude .svn
30 global-exclude .svn
32 global-exclude .bzr
31 global-exclude .bzr
33 global-exclude .hgignore
32 global-exclude .hgignore
General Comments 0
You need to be logged in to leave comments. Login now