~azzar1/unity/add-show-desktop-key

« back to all changes in this revision

Viewing changes to setup.py

  • Committer: mattgiuca
  • Date: 2008-03-07 15:12:02 UTC
  • Revision ID: svn-v3-trunk0:2b9c9e99-6f39-0410-b283-7f802c844ae2:trunk:669
Timestamps are now stored within the program as Python "time" module's
    "struct_time" objects, rather than strings directly from the DB.
    They are parsed into struct_time objects when reading from the db.
    They are formatted into SQL Timestamp strings when writing to the db.
    This allows them to be manipulated and compared within the program.

common.db: _escape now accepts struct_time objects - it formats them into SQL
            time strings.
common.user: The User constructor now parses "acct_exp", "pass_exp" and
            "last_login" fields as timestamp strings, and stores them
            internally as struct_time.
tutorialservice: When recording a submission, the "date" field is now stored
            as a struct_time, not a formatted string.
login.py: When logging in, uncommented call to write last_login to the DB,
            passing the current local time. (This now works correctly).
            Note that this is done after retrieving the user details, so the
            value of last_login stored in the session is the _old_ last login,
            not the new one (this is intentional).

(With Tom Conway).

Show diffs side-by-side

added added

removed removed

Lines of Context:
100
100
    '/bin/echo',
101
101
    # Needed by python
102
102
    '/usr/bin/python%s' % PYTHON_VERSION,
 
103
    # Needed by fileservice
 
104
    '/lib/libcom_err.so.2',
 
105
    '/lib/libcrypt.so.1',
 
106
    '/lib/libkeyutils.so.1',
 
107
    '/lib/libresolv.so.2',
 
108
    '/lib/librt.so.1',
 
109
    '/lib/libuuid.so.1',
 
110
    '/usr/lib/libapr-1.so.0',
 
111
    '/usr/lib/libaprutil-1.so.0',
 
112
    '/usr/lib/libdb-4.4.so',
 
113
    '/usr/lib/libexpat.so.1',
 
114
    '/usr/lib/libgcrypt.so.11',
 
115
    '/usr/lib/libgnutls.so.13',
 
116
    '/usr/lib/libgpg-error.so.0',
 
117
    '/usr/lib/libgssapi_krb5.so.2',
 
118
    '/usr/lib/libk5crypto.so.3',
 
119
    '/usr/lib/libkrb5.so.3',
 
120
    '/usr/lib/libkrb5support.so.0',
 
121
    '/usr/lib/liblber.so.2',
 
122
    '/usr/lib/libldap_r.so.2',
 
123
    '/usr/lib/libneon.so.26',
 
124
    '/usr/lib/libpq.so.5',
 
125
    '/usr/lib/libsasl2.so.2',
 
126
    '/usr/lib/libsqlite3.so.0',
 
127
    '/usr/lib/libsvn_client-1.so.1',
 
128
    '/usr/lib/libsvn_delta-1.so.1',
 
129
    '/usr/lib/libsvn_diff-1.so.1',
 
130
    '/usr/lib/libsvn_fs-1.so.1',
 
131
    '/usr/lib/libsvn_fs_base-1.so.1',
 
132
    '/usr/lib/libsvn_fs_fs-1.so.1',
 
133
    '/usr/lib/libsvn_ra-1.so.1',
 
134
    '/usr/lib/libsvn_ra_dav-1.so.1',
 
135
    '/usr/lib/libsvn_ra_local-1.so.1',
 
136
    '/usr/lib/libsvn_ra_svn-1.so.1',
 
137
    '/usr/lib/libsvn_repos-1.so.1',
 
138
    '/usr/lib/libsvn_subr-1.so.1',
 
139
    '/usr/lib/libsvn_wc-1.so.1',
 
140
    '/usr/lib/libtasn1.so.3',
 
141
    '/usr/lib/libxml2.so.2',
103
142
    # Needed by matplotlib
104
143
    '/usr/lib/i686/cmov/libssl.so.0.9.8',
105
144
    '/usr/lib/i686/cmov/libcrypto.so.0.9.8',
120
159
    '/usr/lib/libXdmcp.so.6',
121
160
    '/lib/libgcc_s.so.1',
122
161
    '/etc/matplotlibrc',
 
162
    # Needed for resolv
 
163
    '/lib/libnss_dns.so.2',
 
164
    #'/lib/libnss_mdns4.so',
 
165
    '/etc/hosts',
 
166
    '/etc/resolv.conf',
 
167
    #'/etc/hosts.conf',
 
168
    #'/etc/hostname',
 
169
    '/etc/nsswitch.conf',
 
170
    '/lib/libnss_files.so.2',
123
171
]
124
172
# Symlinks to make within the jail. Src mapped to dst.
125
173
JAIL_LINKS = {
152
200
 
153
201
# Configuration options, defaults and descriptions
154
202
config_options = []
155
 
config_options.append(ConfigOption("root_dir", "/ivle",
 
203
config_options.append(ConfigOption("root_dir", "/",
156
204
    """Root directory where IVLE is located (in URL space):""",
157
205
    """
158
206
# In URL space, where in the site is IVLE located. (All URLs will be prefixed
165
213
# In the local file system, where IVLE is actually installed.
166
214
# This directory should contain the "www" and "bin" directories."""))
167
215
config_options.append(ConfigOption("jail_base", "/home/informatics/jails",
168
 
    """Root directory where the jails (containing user files) are stored
 
216
    """Location of Directories
 
217
=======================
 
218
Root directory where the jails (containing user files) are stored
169
219
(on the local file system):""",
170
220
    """
171
221
# In the local file system, where are the student/user file spaces located.
179
229
# In the local file system, where are the per-subject file spaces located.
180
230
# The individual subject directories are expected to be located immediately
181
231
# in subdirectories of this location."""))
182
 
config_options.append(ConfigOption("problems_base",
183
 
    "/home/informatics/problems",
184
 
    """Root directory where the problem directories (containing
185
 
subject-independent problem sheets) are stored (on the local file
 
232
config_options.append(ConfigOption("exercises_base",
 
233
    "/home/informatics/exercises",
 
234
    """Root directory where the exercise directories (containing
 
235
subject-independent exercise sheets) are stored (on the local file
186
236
system):""",
187
237
    """
188
 
# In the local file system, where are the subject-independent problem sheet
 
238
# In the local file system, where are the subject-independent exercise sheet
189
239
# file spaces located."""))
190
240
config_options.append(ConfigOption("public_host", "public.localhost",
191
241
    """Hostname which will cause the server to go into "public mode",
222
272
    """Database name:""",
223
273
    """
224
274
# Database name"""))
 
275
config_options.append(ConfigOption("db_forumdbname", "ivle_forum",
 
276
    """Forum Database name:""",
 
277
    """
 
278
# Forum Database name"""))
225
279
config_options.append(ConfigOption("db_user", "postgres",
226
280
    """Username for DB server login:""",
227
281
    """
231
285
    (Caution: This password is stored in plaintext in lib/conf/conf.py)""",
232
286
    """
233
287
# Database password"""))
 
288
config_options.append(ConfigOption("auth_modules", "ldap_auth",
 
289
    """Authentication config
 
290
=====================
 
291
Comma-separated list of authentication modules. Only "ldap" is available
 
292
by default.""",
 
293
    """
 
294
# Comma-separated list of authentication modules.
 
295
# These refer to importable Python modules in the www/auth directory.
 
296
# Modules "ldap" and "guest" are available in the source tree, but
 
297
# other modules may be plugged in to auth against organisation-specific
 
298
# auth backends."""))
 
299
config_options.append(ConfigOption("ldap_url", "ldaps://www.example.com",
 
300
    """(LDAP options are only relevant if "ldap" is included in the list of
 
301
auth modules).
 
302
URL for LDAP authentication server:""",
 
303
    """
 
304
# URL for LDAP authentication server"""))
 
305
config_options.append(ConfigOption("ldap_format_string",
 
306
    "uid=%s,ou=users,o=example",
 
307
    """Format string for LDAP auth request:
 
308
    (Must contain a single "%s" for the user's login name)""",
 
309
    """
 
310
# Format string for LDAP auth request
 
311
# (Must contain a single "%s" for the user's login name)"""))
 
312
config_options.append(ConfigOption("svn_addr", "http://svn.localhost/",
 
313
    """Subversion config
 
314
=================
 
315
The base url for accessing subversion repositories:""",
 
316
    """
 
317
# The base url for accessing subversion repositories."""))
 
318
config_options.append(ConfigOption("svn_conf", "/opt/ivle/svn/svn.conf",
 
319
    """The location of the subversion configuration file used by apache
 
320
to host the user repositories:""",
 
321
    """
 
322
# The location of the subversion configuration file used by
 
323
# apache to host the user repositories."""))
 
324
config_options.append(ConfigOption("svn_repo_path", "/home/informatics/repositories",
 
325
    """The root directory for the subversion repositories:""",
 
326
    """
 
327
# The root directory for the subversion repositories."""))
 
328
config_options.append(ConfigOption("svn_auth_ivle", "/opt/ivle/svn/ivle.auth",
 
329
    """The location of the password file used to authenticate users
 
330
of the subversion repository from the ivle server:""",
 
331
    """
 
332
# The location of the password file used to authenticate users
 
333
# of the subversion repository from the ivle server."""))
 
334
config_options.append(ConfigOption("svn_auth_local", "/opt/ivle/svn/local.auth",
 
335
    """The location of the password file used to authenticate local users
 
336
of the subversion repository:""",
 
337
    """
 
338
# The location of the password file used to authenticate local users
 
339
# of the subversion repository."""))
 
340
config_options.append(ConfigOption("usrmgt_host", "localhost",
 
341
    """User Management Server config
 
342
============================
 
343
The hostname where the usrmgt-server runs:""",
 
344
    """
 
345
# The hostname where the usrmgt-server runs."""))
 
346
config_options.append(ConfigOption("usrmgt_port", "2178",
 
347
    """The port where the usrmgt-server runs:""",
 
348
    """
 
349
# The port where the usrmgt-server runs."""))
 
350
config_options.append(ConfigOption("usrmgt_magic", "",
 
351
    """The password for the usrmgt-server:""",
 
352
    """
 
353
# The password for the usrmgt-server."""))
234
354
 
235
355
# Try importing existing conf, but if we can't just set up defaults
236
356
# The reason for this is that these settings are used by other phases
261
381
# as necessary, and include it in the distribution.
262
382
listmake_mimetypes = ['text/x-python', 'text/html',
263
383
    'application/x-javascript', 'application/javascript',
264
 
    'text/css', 'image/png', 'application/xml']
 
384
    'text/css', 'image/png', 'image/gif', 'application/xml']
265
385
 
266
386
# Main function skeleton from Guido van Rossum
267
387
# http://www.artima.com/weblogs/viewpost.jsp?thread=4829
385
505
Copy subjects/ to subjects directory (unless --nosubjects specified).
386
506
 
387
507
--nojail        Do not copy the jail.
388
 
--nosubjects    Do not copy the subjects and problems directories.
 
508
--nosubjects    Do not copy the subjects and exercises directories.
389
509
--dry | -n  Print out the actions but don't do anything."""
390
510
    elif operation == 'updatejails':
391
511
        print """sudo python setup.py updatejails [--dry|-n]
403
523
    # We build two separate lists, by walking www and console
404
524
    list_www = build_list_py_files('www')
405
525
    list_lib = build_list_py_files('lib')
406
 
    list_console = build_list_py_files('console')
407
526
    list_subjects = build_list_py_files('subjects', no_top_level=True)
408
 
    list_problems = build_list_py_files('problems', no_top_level=True)
 
527
    list_exercises = build_list_py_files('exercises', no_top_level=True)
 
528
    list_scripts = [
 
529
        "scripts/python-console",
 
530
        "scripts/fileservice",
 
531
        "scripts/serveservice",
 
532
        "scripts/usrmgt-server",
 
533
        "scripts/diffservice",
 
534
    ]
409
535
    # Make sure that the files generated by conf are in the list
410
536
    # (since listmake is typically run before conf)
411
537
    if "lib/conf/conf.py" not in list_lib:
412
 
        list_www.append("lib/conf/conf.py")
413
 
    # Make sure that console/python-console is in the list
414
 
    if "console/python-console" not in list_console:
415
 
        list_console.append("console/python-console")
 
538
        list_lib.append("lib/conf/conf.py")
416
539
    # Write these out to a file
417
540
    cwd = os.getcwd()
418
541
    # the files that will be created/overwritten
436
559
list_lib = """)
437
560
        writelist_pretty(file, list_lib)
438
561
        file.write("""
439
 
# List of all installable files in console directory.
440
 
list_console = """)
441
 
        writelist_pretty(file, list_console)
 
562
# List of all installable files in scripts directory.
 
563
list_scripts = """)
 
564
        writelist_pretty(file, list_scripts)
442
565
        file.write("""
443
566
# List of all installable files in subjects directory.
444
567
# This is to install sample subjects and material.
445
568
list_subjects = """)
446
569
        writelist_pretty(file, list_subjects)
447
570
        file.write("""
448
 
# List of all installable files in problems directory.
 
571
# List of all installable files in exercises directory.
449
572
# This is to install sample exercise material.
450
 
list_problems = """)
451
 
        writelist_pretty(file, list_problems)
 
573
list_exercises = """)
 
574
        writelist_pretty(file, list_exercises)
452
575
 
453
576
        file.close()
454
577
    except IOError, (errno, strerror):
494
617
        file.write(']\n')
495
618
 
496
619
def conf(args):
497
 
    global db_port
 
620
    global db_port, usrmgt_port
498
621
    # Set up some variables
499
622
 
500
623
    cwd = os.getcwd()
501
624
    # the files that will be created/overwritten
502
625
    conffile = os.path.join(cwd, "lib/conf/conf.py")
 
626
    jailconffile = os.path.join(cwd, "lib/conf/jailconf.py")
503
627
    conf_hfile = os.path.join(cwd, "trampoline/conf.h")
 
628
    phpBBconffile = os.path.join(cwd, "www/php/phpBB3/config.php")
504
629
 
505
630
    # Get command-line arguments to avoid asking questions.
506
631
 
519
644
        print """This tool will create the following files:
520
645
    %s
521
646
    %s
 
647
    %s
522
648
prompting you for details about your configuration. The file will be
523
649
overwritten if it already exists. It will *not* install or deploy IVLE.
524
650
 
525
651
Please hit Ctrl+C now if you do not wish to do this.
526
 
""" % (conffile, conf_hfile)
 
652
""" % (conffile, jailconffile, conf_hfile)
527
653
 
528
654
        # Get information from the administrator
529
655
        # If EOF is encountered at any time during the questioning, just exit
555
681
        "Invalid DB port (%s).\n"
556
682
        "Must be an integer between 0 and 65535." % repr(db_port))
557
683
        return 1
 
684
    try:
 
685
        usrmgt_port = int(usrmgt_port)
 
686
        if usrmgt_port < 0 or usrmgt_port >= 65536: raise ValueError()
 
687
    except ValueError:
 
688
        print >>sys.stderr, (
 
689
        "Invalid user management port (%s).\n"
 
690
        "Must be an integer between 0 and 65535." % repr(usrmgt_port))
 
691
        return 1
558
692
 
559
693
    # Write lib/conf/conf.py
560
694
 
577
711
 
578
712
    print "Successfully wrote lib/conf/conf.py"
579
713
 
 
714
    # Write conf/jailconf.py
 
715
 
 
716
    try:
 
717
        conf = open(jailconffile, "w")
 
718
 
 
719
        # In the "in-jail" version of conf, we don't need MOST of the details
 
720
        # (it would be a security risk to have them here).
 
721
        # So we just write root_dir, and jail_base is "/".
 
722
        # (jail_base being "/" means "jail-relative" paths are relative to "/"
 
723
        # when inside the jail.)
 
724
        conf.write("""# IVLE Configuration File
 
725
# conf.py
 
726
# Miscellaneous application settings
 
727
# (User jail version)
 
728
 
 
729
 
 
730
# In URL space, where in the site is IVLE located. (All URLs will be prefixed
 
731
# with this).
 
732
# eg. "/" or "/ivle".
 
733
root_dir = %s
 
734
 
 
735
# In the local file system, where are the student/user file spaces located.
 
736
# The user jails are expected to be located immediately in subdirectories of
 
737
# this location.
 
738
jail_base = '/'
 
739
 
 
740
# The hostname for serving publicly accessible pages
 
741
public_host = %s
 
742
""" % (repr(root_dir),repr(public_host)))
 
743
 
 
744
        conf.close()
 
745
    except IOError, (errno, strerror):
 
746
        print "IO error(%s): %s" % (errno, strerror)
 
747
        sys.exit(1)
 
748
 
 
749
    print "Successfully wrote lib/conf/jailconf.py"
 
750
 
580
751
    # Write trampoline/conf.h
581
752
 
582
753
    try:
600
771
 * (Note that root is an implicit member of this list).
601
772
 */
602
773
static const int allowed_uids[] = { %s };
603
 
""" % (jail_base, repr(allowed_uids_list)[1:-1]))
 
774
""" % (repr(jail_base)[1:-1], repr(allowed_uids_list)[1:-1]))
 
775
    # Note: The above uses PYTHON reprs, not C reprs
 
776
    # However they should be the same with the exception of the outer
 
777
    # characters, which are stripped off and replaced
604
778
 
605
779
        conf.close()
606
780
    except IOError, (errno, strerror):
609
783
 
610
784
    print "Successfully wrote trampoline/conf.h"
611
785
 
 
786
    # Write www/php/phpBB3/config.php
 
787
 
 
788
    try:
 
789
        conf = open(phpBBconffile, "w")
 
790
        
 
791
        # php-pg work around
 
792
        if db_host == 'localhost':
 
793
            forumdb_host = '127.0.0.1'
 
794
        else:
 
795
            forumdb_host = db_host
 
796
 
 
797
        conf.write( """<?php
 
798
// phpBB 3.0.x auto-generated configuration file
 
799
// Do not change anything in this file!
 
800
$dbms = 'postgres';
 
801
$dbhost = '""" + forumdb_host + """';
 
802
$dbport = '""" + str(db_port) + """';
 
803
$dbname = '""" + db_forumdbname + """';
 
804
$dbuser = '""" + db_user + """';
 
805
$dbpasswd = '""" + db_password + """';
 
806
 
 
807
$table_prefix = 'phpbb_';
 
808
$acm_type = 'file';
 
809
$load_extensions = '';
 
810
@define('PHPBB_INSTALLED', true);
 
811
// @define('DEBUG', true);
 
812
//@define('DEBUG_EXTRA', true);
 
813
?>"""   )
 
814
    
 
815
        conf.close()
 
816
    except IOError, (errno, strerror):
 
817
        print "IO error(%s): %s" % (errno, strerror)
 
818
        sys.exit(1)
 
819
 
 
820
    print "Successfully wrote www/php/phpBB3/config.php"
 
821
 
612
822
    print
613
823
    print "You may modify the configuration at any time by editing"
614
824
    print conffile
 
825
    print jailconffile
615
826
    print conf_hfile
 
827
    print phpBBconffile
616
828
    print
617
829
    return 0
618
830
 
637
849
    action_mkdir('jail/home', dry)
638
850
    action_mkdir('jail/tmp', dry)
639
851
 
 
852
    # Chmod the tmp directory to world writable
 
853
    action_chmod_w('jail/tmp', dry)
 
854
 
640
855
    # Copy all console and operating system files into the jail
641
 
    action_copylist(install_list.list_console, 'jail/opt/ivle', dry)
 
856
    action_copylist(install_list.list_scripts, 'jail/opt/ivle', dry)
642
857
    copy_os_files_jail(dry)
643
858
    # Chmod the python console
644
 
    action_chmod_x('jail/opt/ivle/console/python-console', dry)
 
859
    action_chmod_x('jail/opt/ivle/scripts/python-console', dry)
 
860
    action_chmod_x('jail/opt/ivle/scripts/fileservice', dry)
 
861
    action_chmod_x('jail/opt/ivle/scripts/serveservice', dry)
645
862
    
 
863
    # Also copy the IVLE lib directory into the jail
 
864
    # This is necessary for running certain scripts
 
865
    action_copylist(install_list.list_lib, 'jail/opt/ivle', dry)
 
866
    # IMPORTANT: The file jail/opt/ivle/lib/conf/conf.py contains details
 
867
    # which could compromise security if left in the jail (such as the DB
 
868
    # password).
 
869
    # The "safe" version is in jailconf.py. Delete conf.py and replace it with
 
870
    # jailconf.py.
 
871
    action_copyfile('lib/conf/jailconf.py',
 
872
        'jail/opt/ivle/lib/conf/conf.py', dry)
646
873
 
647
874
    # Compile .py files into .pyc or .pyo files
648
875
    compileall.compile_dir('www', quiet=True)
649
 
    compileall.compile_dir('console', quiet=True)
 
876
    compileall.compile_dir('lib', quiet=True)
 
877
    compileall.compile_dir('scripts', quiet=True)
 
878
    compileall.compile_dir('jail/opt/ivle/lib', quiet=True)
 
879
 
 
880
    # Set up ivle.pth inside the jail
 
881
    # Need to set /opt/ivle/lib to be on the import path
 
882
    ivle_pth = \
 
883
        "jail/usr/lib/python%s/site-packages/ivle.pth" % PYTHON_VERSION
 
884
    f = open(ivle_pth, 'w')
 
885
    f.write('/opt/ivle/lib\n')
 
886
    f.close()
650
887
 
651
888
    return 0
652
889
 
694
931
    # chown trampoline to root and set setuid bit
695
932
    action_chown_setuid(tramppath, dry)
696
933
 
 
934
    # Create a scripts directory to put the usrmgt-server in.
 
935
    action_mkdir(os.path.join(ivle_install_dir, 'scripts'), dry)
 
936
    usrmgtpath = os.path.join(ivle_install_dir, 'scripts/usrmgt-server')
 
937
    action_copyfile('scripts/usrmgt-server', usrmgtpath, dry)
 
938
    action_chmod_x(usrmgtpath, dry)
 
939
 
697
940
    # Copy the www and lib directories using the list
698
941
    action_copylist(install_list.list_www, ivle_install_dir, dry)
699
942
    action_copylist(install_list.list_lib, ivle_install_dir, dry)
 
943
    
 
944
    # Copy the php directory
 
945
    action_copytree('www/php/phpBB3',os.path.join(ivle_install_dir,'www/php/phpBB3'), 
 
946
    dry)
700
947
 
701
948
    if not nojail:
702
949
        # Copy the local jail directory built by the build action
704
951
        # for all the students' jails).
705
952
        action_copytree('jail', os.path.join(jail_base, 'template'), dry)
706
953
    if not nosubjects:
707
 
        # Copy the subjects and problems directories across
 
954
        # Copy the subjects and exercises directories across
708
955
        action_copylist(install_list.list_subjects, subjects_base, dry,
709
956
            srcdir="./subjects")
710
 
        action_copylist(install_list.list_problems, problems_base, dry,
711
 
            srcdir="./problems")
 
957
        action_copylist(install_list.list_exercises, exercises_base, dry,
 
958
            srcdir="./exercises")
712
959
 
713
960
    # Append IVLE path to ivle.pth in python site packages
714
961
    # (Unless it's already there)
799
1046
    if ret != 0:
800
1047
        raise RunError(prog, ret)
801
1048
 
 
1049
def action_remove(path, dry):
 
1050
    """Calls rmtree, deleting the target file if it exists."""
 
1051
    try:
 
1052
        print "rm -r", path
 
1053
        if not dry:
 
1054
            shutil.rmtree(path, True)
 
1055
    except OSError, (err, msg):
 
1056
        if err != errno.EEXIST:
 
1057
            raise
 
1058
        # Otherwise, didn't exist, so we don't care
 
1059
 
802
1060
def action_rename(src, dst, dry):
803
1061
    """Calls rename. Deletes the target if it already exists."""
804
 
    if os.access(dst, os.F_OK):
805
 
        print "rm -r", dst
806
 
        if not dry:
807
 
            shutil.rmtree(dst, True)
 
1062
    action_remove(dst, dry)
808
1063
    print "mv ", src, dst
809
1064
    if dry: return
810
1065
    try:
830
1085
    directories as necessary.
831
1086
 
832
1087
    See shutil.copytree."""
833
 
    if os.access(dst, os.F_OK):
834
 
        print "rm -r", dst
835
 
        if not dry:
836
 
            shutil.rmtree(dst, True)
 
1088
    # Allow copying over itself
 
1089
    if (os.path.normpath(os.path.join(os.getcwd(),src)) ==
 
1090
        os.path.normpath(os.path.join(os.getcwd(),dst))):
 
1091
        return
 
1092
    action_remove(dst, dry)
837
1093
    print "cp -r", src, dst
838
1094
    if dry: return
839
1095
    shutil.copytree(src, dst, True)
842
1098
    """Hard-links an entire directory tree. Same as copytree but the created
843
1099
    files are hard-links not actual copies. Removes the existing destination.
844
1100
    """
845
 
    if os.access(dst, os.F_OK):
846
 
        print "rm -r", dst
847
 
        if not dry:
848
 
            shutil.rmtree(dst, True)
 
1101
    action_remove(dst, dry)
849
1102
    print "<cp with hardlinks> -r", src, dst
850
1103
    if dry: return
851
1104
    common.makeuser.linktree(src, dst)
926
1179
        os.chmod(file, stat.S_IXUSR | stat.S_IRUSR | stat.S_IWUSR
927
1180
            | stat.S_IXGRP | stat.S_IRGRP | stat.S_IXOTH | stat.S_IROTH)
928
1181
 
 
1182
 
 
1183
def action_chmod_w(file, dry):
 
1184
    """Chmod 777 a file (sets permissions to rwxrwxrwx)."""
 
1185
    print "chmod 777", file
 
1186
    if not dry:
 
1187
        os.chmod(file, stat.S_IXUSR | stat.S_IRUSR | stat.S_IWUSR
 
1188
            | stat.S_IXGRP | stat.S_IWGRP | stat.S_IRGRP | stat.S_IXOTH
 
1189
            | stat.S_IWOTH | stat.S_IROTH)
 
1190
 
929
1191
def query_user(default, prompt):
930
1192
    """Prompts the user for a string, which is read from a line of stdin.
931
1193
    Exits silently if EOF is encountered. Returns the string, with spaces