[124047] trunk/base

ksammons at macports.org ksammons at macports.org
Sun Aug 17 12:09:55 PDT 2014


Revision: 124047
          https://trac.macports.org/changeset/124047
Author:   ksammons at macports.org
Date:     2014-08-17 12:09:55 -0700 (Sun, 17 Aug 2014)
Log Message:
-----------
Merge from gsoc14-cleanup. See https://trac.macports.org/wiki/SummerOfCode2014#cleanup for details.

Modified Paths:
--------------
    trunk/base/doc/Makefile.in
    trunk/base/src/macports1.0/Makefile.in
    trunk/base/src/macports1.0/macports.tcl
    trunk/base/src/port/port.tcl

Added Paths:
-----------
    trunk/base/doc/port-doctor.1
    trunk/base/doc/port-doctor.1.txt
    trunk/base/doc/port-reclaim.1
    trunk/base/doc/port-reclaim.1.txt
    trunk/base/src/macports1.0/doctor.tcl
    trunk/base/src/macports1.0/reclaim.tcl
    trunk/base/src/macports1.0/tests/reclaim.test

Property Changed:
----------------
    trunk/base/


Property changes on: trunk/base
___________________________________________________________________
Modified: svn:mergeinfo
   - /branches/gsoc08-privileges/base:37343-46937
/branches/gsoc09-logging/base:51231-60371
/branches/gsoc11-rev-upgrade/base:78828-88375
/branches/gsoc11-statistics/base:79520,79666
/branches/gsoc13-tests:106692-111324
/branches/universal-sanity/base:51872-52323
/branches/variant-descs-14482/base:34469-34855,34900-37508,37511-37512,41040-41463,42575-42626,42640-42659
/users/perry/base-bugs_and_notes:45682-46060
/users/perry/base-select:44044-44692
   + /branches/gsoc08-privileges/base:37343-46937
/branches/gsoc09-logging/base:51231-60371
/branches/gsoc11-rev-upgrade/base:78828-88375
/branches/gsoc11-statistics/base:79520,79666
/branches/gsoc13-tests:106692-111324
/branches/gsoc14-cleanup:123738-124046
/branches/universal-sanity/base:51872-52323
/branches/variant-descs-14482/base:34469-34855,34900-37508,37511-37512,41040-41463,42575-42626,42640-42659
/users/perry/base-bugs_and_notes:45682-46060
/users/perry/base-select:44044-44692

Modified: trunk/base/doc/Makefile.in
===================================================================
--- trunk/base/doc/Makefile.in	2014-08-17 19:01:31 UTC (rev 124046)
+++ trunk/base/doc/Makefile.in	2014-08-17 19:09:55 UTC (rev 124047)
@@ -35,6 +35,7 @@
 		port-distcheck.1 \
 		port-distfiles.1 \
 		port-dmg.1 \
+        port-doctor.1 \
 		port-echo.1 \
 		port-edit.1 \
 		port-exit.1 \
@@ -57,6 +58,7 @@
 		port-quit.1 \
 		port-rdependents.1 \
 		port-rdeps.1 \
+        port-reclaim.1 \
 		port-rev-upgrade.1 \
 		port-selfupdate.1 \
 		port-uninstall.1 \

Copied: trunk/base/doc/port-doctor.1 (from rev 124046, branches/gsoc14-cleanup/doc/port-doctor.1)
===================================================================
--- trunk/base/doc/port-doctor.1	                        (rev 0)
+++ trunk/base/doc/port-doctor.1	2014-08-17 19:09:55 UTC (rev 124047)
@@ -0,0 +1,53 @@
+'\" t
+.TH "PORT\-DOCTOR" "1" "08/17/2014" "MacPorts 2\&.3\&.99" "MacPorts Manual"
+.\" -----------------------------------------------------------------
+.\" * Define some portability stuff
+.\" -----------------------------------------------------------------
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.\" http://bugs.debian.org/507673
+.\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.ie \n(.g .ds Aq \(aq
+.el       .ds Aq '
+.\" -----------------------------------------------------------------
+.\" * set default formatting
+.\" -----------------------------------------------------------------
+.\" disable hyphenation
+.nh
+.\" disable justification (adjust text to left margin only)
+.ad l
+.\" -----------------------------------------------------------------
+.\" * MAIN CONTENT STARTS HERE *
+.\" -----------------------------------------------------------------
+.SH "NAME"
+port-doctor \- Detects common issues
+.SH "SYNOPSIS"
+.sp
+.nf
+\fBport doctor\fR
+        [\-\-quiet]
+.fi
+.SH "DESCRIPTION"
+.sp
+\fBport doctor\fR will check a list of common issues that could affect the user or MacPorts in one way or another\&. If any issues are found, a warning will be shown to the user included with a possible fix for said problem\&.
+.SH "OPTIONS"
+.PP
+\fB\-\-quiet\fR
+.RS 4
+Only display warnings or errors\&.
+.RE
+.SH "SEE ALSO"
+.sp
+\fBport\fR(1)
+.SH "AUTHORS"
+.sp
+.if n \{\
+.RS 4
+.\}
+.nf
+(C) 2014 The MacPorts Project
+Kyle Sammons <ksammons at macports\&.org>
+.fi
+.if n \{\
+.RE
+.\}

Copied: trunk/base/doc/port-doctor.1.txt (from rev 124046, branches/gsoc14-cleanup/doc/port-doctor.1.txt)
===================================================================
--- trunk/base/doc/port-doctor.1.txt	                        (rev 0)
+++ trunk/base/doc/port-doctor.1.txt	2014-08-17 19:09:55 UTC (rev 124047)
@@ -0,0 +1,34 @@
+// vim: set et sw=4 ts=8 ft=asciidoc tw=80:
+port-doctor(1)
+==============
+$Id$
+
+NAME
+----
+port-doctor - Detects common issues 
+
+SYNOPSIS
+--------
+[cmdsynopsis]
+*port doctor*
+        [--quiet]
+
+DESCRIPTION
+-----------
+*port doctor* will check a list of common issues that could affect the user or
+MacPorts in one way or another. If any issues are found, a warning will be
+shown to the user included with a possible fix for said problem.
+
+OPTIONS
+-------
+*--quiet*::
+Only display warnings or errors.
+
+SEE ALSO
+--------
+man:port[1]
+
+AUTHORS
+-------
+ (C) 2014 The MacPorts Project
+ Kyle Sammons <ksammons at macports.org>

Copied: trunk/base/doc/port-reclaim.1 (from rev 124046, branches/gsoc14-cleanup/doc/port-reclaim.1)
===================================================================
--- trunk/base/doc/port-reclaim.1	                        (rev 0)
+++ trunk/base/doc/port-reclaim.1	2014-08-17 19:09:55 UTC (rev 124047)
@@ -0,0 +1,49 @@
+'\" t
+.TH "PORT\-RECLAIM" "1" "08/17/2014" "MacPorts 2\&.3\&.99" "MacPorts Manual"
+.\" -----------------------------------------------------------------
+.\" * Define some portability stuff
+.\" -----------------------------------------------------------------
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.\" http://bugs.debian.org/507673
+.\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.ie \n(.g .ds Aq \(aq
+.el       .ds Aq '
+.\" -----------------------------------------------------------------
+.\" * set default formatting
+.\" -----------------------------------------------------------------
+.\" disable hyphenation
+.nh
+.\" disable justification (adjust text to left margin only)
+.ad l
+.\" -----------------------------------------------------------------
+.\" * MAIN CONTENT STARTS HERE *
+.\" -----------------------------------------------------------------
+.SH "NAME"
+port-reclaim \- Reclaims disk space\&.
+.SH "SYNOPSIS"
+.sp
+.nf
+\fBport\fR [\fB\-vd\fR] \fBreclaim\fR
+.fi
+.SH "DESCRIPTION"
+.sp
+\fBport reclaim\fR will reclaim disk space by uninstalling inactive ports on your system, and removing unneeded or unused installation files\&.
+.SH "GLOBAL OPTIONS"
+.sp
+Please see the section \fBGLOBAL OPTIONS\fR in the \fBport\fR(1) man page for a description of global port options\&.
+.SH "SEE ALSO"
+.sp
+\fBport\fR(1), \fBport-uninstall\fR(1), \fBport-clean\fR(1),
+.SH "AUTHORS"
+.sp
+.if n \{\
+.RS 4
+.\}
+.nf
+(C) 2014 The MacPorts Project
+Kyle Sammons <ksammons at macports\&.org>
+.fi
+.if n \{\
+.RE
+.\}

Copied: trunk/base/doc/port-reclaim.1.txt (from rev 124046, branches/gsoc14-cleanup/doc/port-reclaim.1.txt)
===================================================================
--- trunk/base/doc/port-reclaim.1.txt	                        (rev 0)
+++ trunk/base/doc/port-reclaim.1.txt	2014-08-17 19:09:55 UTC (rev 124047)
@@ -0,0 +1,29 @@
+// vim: set et sw=4 ts=8 ft=asciidoc tw=80:
+port-reclaim(1)
+===============
+$Id$
+
+NAME
+----
+port-reclaim -  Reclaims disk space. 
+
+SYNOPSIS
+--------
+[cmdsynopsis]
+*port* [*-vd*] *reclaim*
+
+DESCRIPTION
+-----------
+*port reclaim* will reclaim disk space by uninstalling inactive ports on your
+system, and removing unneeded or unused installation files.
+
+include::global-flags.txt[]
+
+SEE ALSO
+--------
+man:port[1], man:port-uninstall[1], man:port-clean[1], 
+
+AUTHORS
+-------
+ (C) 2014 The MacPorts Project
+ Kyle Sammons <ksammons at macports.org>

Modified: trunk/base/src/macports1.0/Makefile.in
===================================================================
--- trunk/base/src/macports1.0/Makefile.in	2014-08-17 19:01:31 UTC (rev 124046)
+++ trunk/base/src/macports1.0/Makefile.in	2014-08-17 19:09:55 UTC (rev 124047)
@@ -4,7 +4,7 @@
 include ../../Mk/macports.autoconf.mk
 
 SRCS=		macports.tcl macports_dlist.tcl macports_util.tcl \
-		macports_autoconf.tcl
+		macports_autoconf.tcl doctor.tcl reclaim.tcl
 OBJS=		macports.o get_systemconfiguration_proxies.o sysctl.o
 SHLIB_NAME=	MacPorts${SHLIB_SUFFIX}
 

Copied: trunk/base/src/macports1.0/doctor.tcl (from rev 124046, branches/gsoc14-cleanup/src/macports1.0/doctor.tcl)
===================================================================
--- trunk/base/src/macports1.0/doctor.tcl	                        (rev 0)
+++ trunk/base/src/macports1.0/doctor.tcl	2014-08-17 19:09:55 UTC (rev 124047)
@@ -0,0 +1,738 @@
+# -*- coding: utf-8; mode: tcl; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- vim:fenc=utf-8:filetype=tcl:et:sw=4:ts=4:sts=4
+# doctor.tcl
+# $Id: doctor.tcl 119177 2014-04-18 22:35:29Z cal at macports.org $
+#
+# Copyright (c) 2002 - 2003 Apple Inc.
+# Copyright (c) 2004 - 2005 Paul Guyot, <pguyot at kallisys.net>.
+# Copyright (c) 2004 - 2006 Ole Guldberg Jensen <olegb at opendarwin.org>.
+# Copyright (c) 2004 - 2005 Robert Shaw <rshaw at opendarwin.org>
+# Copyright (c) 2004 - 2014 The MacPorts Project
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+# 3. Neither the name of Apple Inc. nor the names of its contributors
+#    may be used to endorse or promote products derived from this software
+#    without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+
+# Todo:
+
+# Done:
+# Add -q for quiet mode, where we don't print anything
+# Check for command line tools
+# Check for any DYLD_* environmental variables
+# Check for '.la' in dylib and '.prl'
+# Check if installed files are readable 
+# Check for sqlite
+# Check for openssl
+# Crowd-source more ideas from the mailing-list
+# Check if $PATH is first
+# Check for issues with compilation. Compile small, simple file, check for "couldn't create cache file"
+# check_for_stray_developer_directory
+# Check for *.h, *.hpp, *.hxx in /usr/local/include
+# Check for *.dylib in /usr/local/lib
+# Check for other package managers. Fink = /sw, homebrew = /usr/local/Cellar
+# Check for all files installed by ports exists
+# Check for archives from all ports exists
+# Check for things in /usr/local
+# Check for x11.app if the OS is 10.6 and suggest installing xorg-server or the site on macosforge
+# Add error catching for line's without an equals sign. 
+# Support comments for the parser
+# Check for amount of drive space
+# Move port_doctor.ini to the port tree, below _resources 
+# Check for curl
+# Check for rsync
+# Check if macports is in /opt/local
+
+
+package provide doctor 1.0 
+
+package require macports
+package require reclaim 1.0
+
+namespace eval doctor {
+
+    # Command line argument that determines whether or not to output things fancily. 
+    variable quiet 0
+    
+    proc main {opts} {
+        
+        # The main function. Handles all the calls to the correct functions, and sets the config_options array, 
+        # as well as the parser_options array.
+        #
+        # Args:
+        #           opts - The options passed in. Currently the only option availible is 'quiet'. 
+        # Returns:
+        #           None
+
+        # Setting the 'quiet' variable based on what was passed in.
+        if {$opts ne ""} {
+            set doctor::quiet 1
+        } else {
+            set doctor::quiet 0
+        }
+
+        array set config_options    [list]
+        set parser_options          {"macports_location" "profile_path" "shell_location" "xcode_version_10.10" "xcode_version_10.9" "xcode_version_10.8" \
+                                    "xcode_version_10.7" "xcode_version_10.6" "xcode_version_10.7" "xcode_version_10.6" "xcode_version_10.5" \
+                                    "xcode_version_10.4" "xcode_build"}
+
+        set user_config_path        ${macports::portdbpath}/port_doctor.ini
+        set xcode_config_path       [macports::getdefaultportresourcepath "macports1.0/xcode_versions.ini"] 
+
+        # Make sure at least a default copy of the xcode and user config exist
+        make_xcode_config $xcode_config_path
+        make_user_config  $user_config_path
+
+        # Read the config files
+        get_config config_options $parser_options $user_config_path 
+        get_config config_options $parser_options $xcode_config_path 
+
+        # Start the checks
+        check_path $config_options(macports_location) $config_options(profile_path) $config_options(shell_location)
+        check_xcode config_options
+        check_for_app curl
+        check_for_app rsync
+        check_for_app openssl
+        check_for_app sqlite3
+        check_macports_location
+        check_free_space
+        check_for_x11
+        check_for_files_in_usr_local 
+        check_tarballs 
+        check_port_files 
+        check_for_package_managers
+        check_for_stray_developer_directory
+        check_compilation_error_cache
+        check_for_dyld
+        check_for_clt
+    }
+
+    proc check_for_clt {} {
+
+        # Checks to see if the Xcode Command Line Tools are installed by checking if the file
+        # /Library/Developer/CommandLineTools exists if the system is running 10.9, or if they're
+        # running an older version, if the command xcode-select -p outputs something.
+        #
+        # Args:
+        #           None
+        # Returns:
+        #           None
+
+        output "command line tools"
+
+        set version ${macports::macosx_version}
+
+        if {$version == 10.9} {
+
+            if {![file exists "/Library/Developer/CommandLineTools/"]} {
+
+                ui_warn "Xcode Command Line Tools are not installed! To install them, please enter the command:
+                                    xcode-select --install"
+                success_fail 0
+                return
+            }
+            success_fail 1
+            return
+
+        } else {
+
+            set xcode_select [exec xcode-select -p]
+
+            if {$xcode_select eq ""} {
+
+                ui_warn "Xcode Command Line Tools are not installed! To install them, please enter the command:
+                                    xcode-selct --install"
+                success_fail 0
+                return
+            }
+            success_fail 1
+        }
+    }
+
+    proc check_for_dyld {} {
+
+        # Checks to see if the current MacPorts session is running with a DYLD_* environmental 
+        # variable set.
+        #
+        # Args:
+        #           None
+        # Returns:
+        #           None
+
+        output "DYLD_* environmental variables"
+
+        set printenv        [exec printenv]
+        set split           [split $printenv]
+
+        if {[regexp {DYLD_.} $split]} {
+            ui_warn "found a DYLD_* environmental variable. These are known to cause issues with MacPorts. Please\
+                     unset the variable for the duration MacPorts is running."
+
+            success_fail 0
+            return
+        }
+
+        success_fail 1
+   }
+
+    proc output {string} {
+        
+        # Outputs the given string formatted correctly.
+        #
+        # Args:
+        #           string - The string to be output 
+        # Returns:
+        #           None
+
+        if {${doctor::quiet} == 0} {
+            ui_msg -nonewline "Checking for $string... "
+        }
+    }
+
+    proc success_fail {result} {
+
+        # Either outputs a [SUCCESS] or [FAILED], depending on the result.
+        #
+        # Args:
+        #           result - An integer value. 1 = [SUCCESS], anything else = [FAILED]
+        # Returns:
+        #           None
+
+        if {${doctor::quiet} eq 0} {
+
+            if {$result == 1} {
+
+                ui_msg "\[SUCCESS\]"
+                return
+            }
+
+            ui_msg "\[FAILED\]"
+        }
+    }
+
+    proc check_compilation_error_cache {} {
+
+        # Checks to see if the compiler can compile properly, or it throws the error, "couldn't create cache file".
+        #
+        # Args: 
+        #           None
+        # Returns:
+        #           None
+
+        output "compilation errors"
+
+        set filename    "test.c"
+        set fd          [open $filename w]
+        
+        puts $fd "int main() { return 0; }"
+        close $fd
+
+        set output      [exec clang $filename -o main_test]
+
+        file delete $filename
+        file delete "main_test"
+
+        if {"couldn't create cache file" in $output} {
+            ui_warn "found errors when attempting to compile file. To fix this issue, delete your tmp folder using:
+                       rm -rf \$TMPDIR"
+            success_fail 0 
+            return
+        }
+
+        success_fail 1 
+       
+    }
+
+    proc check_for_stray_developer_directory {} {
+
+        # Checks to see if the script to remove leftover files from Xcode has been run or not. Implementation heavily influenced
+        # by Homebrew implementation. 
+        #
+        # Args:
+        #           None
+        # Returns:
+        #           None
+
+        output "stray developer directory"
+        
+        set uninstaller "/Developer/Library/uninstall-developer-folder"
+        
+        if {${macports::xcodeversion} >= 4.3 && [file exists $uninstaller]} { 
+            ui_warn "you have leftover files from an older version of Xcode. You should delete them by using, $uninstaller"
+
+            success_fail 0 
+            return
+        } 
+
+        success_fail 1 
+    }
+
+    proc check_for_package_managers {} {
+
+        # Checks to see if either Fink or Homebrew are installed on the system. If they are, it warns them and suggest they uninstall
+        # or move them to a different location.
+        # 
+        # Args:
+        #           None
+        # Returns:
+        #           None
+
+        output "HomeBrew"
+        
+        if {[file exists "/usr/local/Cellar"]} {
+            ui_warn "it seems you have Homebrew installed on this system -- Because Homebrew uses /usr/local, this can potentially cause issues \
+                     with MacPorts. We'd recommend you either uninstall it, or move it from /usr/local for now."
+
+            success_fail 0
+
+        } else {
+
+            success_fail 1
+        }
+
+        output "Fink"
+        if {[file exists "/sf"]} {
+            ui_warn "it seems you have Fink installed on your system -- This could potentially cause issues with MacPorts. We'd recommend you'd \
+                     either uninstall it, or move it from /sf for now."
+
+            success_fail 0
+ 
+        } else {
+
+            success_fail 1
+        }
+    }
+
+    proc check_port_files {} {
+        
+        # Checks to see if each file installed by all active and installed ports actually exists on the filesystem. If not, it warns
+        # the user and suggests the user deactivate and reactivate the port.
+        #
+        # Args:
+        #           None
+        # Returns:
+        #           None
+
+
+        set apps [reclaim::get_info]
+
+        array set activeApps {}
+        set totalFiles 0
+
+        foreach app $apps {
+
+            set name    [lindex $app 0]
+            set active  [lindex $app 4]
+            set files   [registry::port_registered $name]
+
+            if {$active} {
+                set activeApps($name) $files
+                incr totalFiles [llength $files]
+            }
+        }
+
+        set fancyOutput [expr {![macports::ui_isset ports_debug] && ![macports::ui_isset ports_verbose] && [info exists macports::ui_options(progress_generic)]}]
+        if {$fancyOutput} {
+            set progress $macports::ui_options(progress_generic)
+        }
+
+        if {$totalFiles > 0} {
+            if {$fancyOutput} {
+                output "files installed by ports on disk"
+                if {${doctor::quiet} == 0} {
+                    # we need a newline here or the progress bar will overwrite the line
+                    ui_msg ""
+                }
+                $progress start
+            }
+
+            set currentFile 1
+            foreach name [lsort [array names activeApps]] {
+                foreach file $activeApps($name) {
+                    if {$fancyOutput} {
+                        $progress update $currentFile $totalFiles
+                    } else {
+                        output "file '$file' on disk"
+                    }
+
+                    if {![file exists $file]} {
+                        if {$fancyOutput} {
+                            $progress intermission
+                        } else {
+                            success_fail 0
+                        }
+
+                        ui_warn "couldn't find file '$file' for port '$name'. Please deactivate and reactivate the port to fix this issue."
+                    } elseif {![file readable $file]} {
+                        if {$fancyOutput} {
+                            $progress intermission
+                        } else {
+                            success_fail 0
+                        }
+
+                        ui_warn "'$file' installed by port '$name' is currently not readable. Please try again. If this problem persists, please contact the mailing list."
+                    } elseif {!$fancyOutput} {
+                        success_fail 1
+                    }
+
+                    incr currentFile
+                }
+            }
+
+            if {$fancyOutput} {
+                $progress finish
+            }
+        }
+    }
+
+    proc check_tarballs {} {
+
+        # Checks if the archives for each installed port in /opt/local/var/macports/software/$name is actually in there. If not, it warns
+        # the user and suggest a reinstallation of the port. 
+        #
+        # Args:
+        #           None
+        # Returns:
+        #           None
+
+        set apps [reclaim::get_info]
+
+        foreach app $apps {
+
+
+            set name        [lindex $app 0]
+            set version     [lindex $app 1]
+            set revision    [lindex $app 2]
+            set variants    [lindex $app 3]
+            set epoch       [lindex $app 5]
+
+            output "'${name} @${version}_${revision}${variants}'s tarball on disk"
+
+            set ref         [registry::open_entry $name $version $revision $variants $epoch]
+            set image_dir   [registry::property_retrieve $ref location]
+
+            if {![file exists $image_dir]} {
+                ui_warn "couldn't find the archive for '$name'. Please uninstall and reinstall this application."
+                success_fail 0
+            } else {
+                success_fail 1
+            }
+        }
+    }
+
+    proc check_for_files_in_usr_local {} {
+
+        # Checks for dylibs in /usr/local/lib and header files in /usr/local/include, and warns the user about said files if they 
+        # are found.
+        # 
+        # Args:
+        #           None 
+        # Returns:
+        #           None
+
+        output "dylibs in /usr/local/lib"
+
+        if {[glob -nocomplain -directory "/usr/local/lib" *.dylib *.la *.prl] ne ""} {
+            ui_warn "found dylib's in your /usr/local/lib directory. These are known to cause problems. We'd recommend \
+                     you remove them."
+
+            success_fail 0
+
+        } else {
+
+            success_fail 1
+        }
+
+        output "header files in /usr/local/include"
+
+        if {[glob -nocomplain -directory "/usr/local/include" *.h *.hpp *.hxx] ne ""} {
+            ui_warn "found header files in your /usr/local/include directory. These are known to cause problems. We'd recommend \
+                     you remove them."
+
+            success_fail 0
+
+        } else {
+
+            success_fail 1
+        }
+    }
+
+    proc check_for_x11 {} {
+
+        # Checks to see if the user is using the X11.app, and if they're on 10.6. If they are, it alerts them about it.
+        #
+        # Args:
+        #           None
+        # Returns:
+        #           None
+
+        output "X11.app on OS X 10.6 systems"
+
+        set mac_version ${macports::macosx_version}
+
+        if {$mac_version == 10.6} {
+
+            if {[file exists /Applications/X11.app]} {
+                ui_error "it seems you have Mac OSX 10.6 installed, and are using X11 from \"X11.app\". This has been known to cause issues. \
+                         To fix this, please install xorg-server, by using the command 'sudo port install xorg-server', or installing it from \
+                         their website, http://xquartz.macosforge.org/trac/wiki/Releases."
+
+                success_fail 0
+                return
+            }
+        }
+
+        success_fail 1
+    }
+
+    proc check_free_space {} {
+
+        # Checks to see if the user has less than 5 gigs of space left, and warns if they don't.
+        #
+        # Args:
+        #           None
+        # Returns:
+        #           None
+
+        output "free disk space"
+
+        set output          [exec df -g]
+        set tokens          [split $output \n]
+        set disk_info       [lindex $tokens 1]
+        set availible       [lindex $disk_info 3]
+
+        if {$availible < 5} {
+            ui_warn "you have less than 5 gigabytes free on your machine! This can cause serious errors. We recommend trying to clear out unnecessary \
+                     programs and files by running 'sudo port reclaim', or manually uninstalling/deleting programs and folders on your drive."
+
+            success_fail 0
+            return
+        }
+
+        success_fail 1
+    }
+
+    proc check_macports_location {} {
+
+        # Checks to see if port is where it should be. If it isn't, freak the frick out.
+        #
+        # Args:
+        #           None
+        # Returns:
+        #           None
+
+        output "MacPort's location"
+
+        if {[file exists ${macports::prefix}/bin/port] == 0} {
+            ui_error "port was not in ${macports::prefix}/bin. This can potentially cause errors. It's recommended you move it back to ${macports::prefix}/bin."
+            success_fail 0
+            return
+        }
+
+        success_fail 1
+   }
+
+    proc check_for_app {app} {
+
+        # Check's if the binary supplied exists in /usr/bin. If it doesn't, it warns the user. 
+        #
+        # Args:
+        #           app - The name of the app to check for.
+        # Returns
+        #           None
+
+        output "for '$app'"
+
+        if {[file exists /usr/bin/$app] == 0} {
+            ui_error "$app is needed by MacPorts to function normally, but wasn't found on this system. We'd recommend \
+                      installing it for continued use of MacPorts." 
+            success_fail 0
+            return
+        }
+
+        success_fail 1
+    }
+
+    proc check_xcode {config_options} {
+        
+        # Checks to see if the currently installed version of Xcode works with the curent OS version.
+        # 
+        # Args:
+        #           config_options - The associative array containing all options in the config files
+        # Returns:
+        #           None
+
+        output "correct Xcode version"
+
+        upvar $config_options config 
+
+        set mac_version     ${macports::macosx_version}
+        set xcode_current   ${macports::xcodeversion} 
+        set xcode_versions  $config(xcode_version_$mac_version)
+
+        if {$xcode_current in $xcode_versions} {
+            success_fail 1
+            return
+        
+        } else {
+            ui_error "currently installed version of Xcode, $xcode_current, is not supported by MacPorts. \
+                      For your currently installed system, only the following versions of Xcode are supported: \
+                      $xcode_versions"
+            success_fail 0
+        }
+    }
+
+    proc make_xcode_config {path} {
+        
+        # Checks to see if xcode_versions.ini exists. If it does, it returns. If it doesn't, then it creats a defult config file.
+        # 
+        # Args: 
+        #           None
+        # Returns:
+        #           None
+
+        if {[file exists $path] == 0} {
+            ui_error "No configuration file found at $path. Please run, 
+                        \"port selfupdate\""
+            exit
+            
+        }
+    }
+     
+    proc make_user_config {path} {
+
+        # Builds a config file for the user using all default parameters if needed.
+        #
+        # Args:
+        #           None
+        # Returns:
+        #           None
+
+        if {[file exists $path] == 0} {
+
+            ui_warn "No configuration file found at $path. Creating generic config file."
+           
+            set fd      [open $path w]
+            puts $fd "macports_location=${macports::prefix}"
+            puts $fd "profile_path=${macports::user_home}/.bash_profile"
+            puts $fd "shell_location=/bin/bash"
+           
+            close $fd
+        }
+   }
+
+    proc get_config {config_options parser_options path} {
+
+        # Reads in and parses the configuration file passed in to $path. After parsing, all variables found are assigned 
+        # in the 'config_options' associative array. 
+        #
+        # Args:
+        #           config_options - The associative array responsible for holding all the configuration options.
+        #           parser_options - The list responsible for holding each option to set/look for in the configuration file.
+        #           path           - The path to the correct config_file
+        # Returns:
+        #           None. 
+
+        upvar $config_options config 
+
+        set fd   [open $path r]
+        set text [read $fd]
+        set data [split $text "\n"]
+
+        close $fd
+
+        foreach line $data { 
+
+            # Ignore comments
+            if {[string index $line 0] eq "#" } {
+                continue
+            }
+
+            #The tokens
+            set tokens [split $line "="]
+
+            # Only care about things that are in $parser_options
+            if {[lindex $tokens 0] in $parser_options} {
+                set config([lindex $tokens 0]) [lindex $tokens 1]
+            
+            # Ignore whitespace
+            } elseif {[lindex $tokens 0] eq ""} {
+                continue
+
+            } else {
+                ui_error "unrecognized config option in file $path: [lindex $tokens 0]"
+            }
+        }
+    }
+
+    proc check_path {port_loc profile_path shell_loc} {
+
+        # Checks to see if port_location/bin and port_location/sbin are in the environmental $PATH variable.
+        # If they aren't, it appends it to the correct shell's profile file.
+        #
+        # Args:
+        #           port_loc        - The location of port (as set in the config file)
+        #           profile_path    - The location of the profile file (as set in the config file)
+        #           shell_loc       - The location of the shell binary (as set in the config file)
+        # Returns:
+        #           None.
+
+        set path ${macports::user_path}
+        set split [split $path :]
+
+        if {"$port_loc/bin" in $split && "$port_loc/sbin" in $split } {
+
+            if {[lindex $split 0] != "$port_loc/bin"} {
+                ui_warn "$port_loc/bin is not first in your PATH environmental variable.  This may or may not \
+                         cause problems in the future."
+            }
+            return
+
+        } else {
+            ui_warn "your environmental \$PATH variable does not currently include, $port_loc/bin, which is where port is located. \
+                     Would you like to add $port_loc/bin to your \$PATH variable now? \[Y/N\]"
+            set input [gets stdin]
+
+            if {$input == "y" || $input == "Y"} {
+                ui_msg "Attempting to add $port_loc/bin to $profile_path"
+
+                if {[file exists $profile_path] == 1} {
+                    set fd [open $profile_path a]
+
+                } else {
+                    ui_error "$profile_path does not exist."
+                }
+
+                puts $fd "export PATH=$port_loc/bin:$port_loc/sbin:\$PATH"
+                close $fd
+
+                ui_msg "Added PATH properly. Please execute, 'source $profile_path' in a new terminal window."
+
+            } elseif {$input == "n" || $input == "N"} {    
+                ui_msg "Not fixing your \$PATH variable."
+
+            } else {
+                ui_msg "Not a valid choice: $input"
+            }
+       }
+   }
+}

Modified: trunk/base/src/macports1.0/macports.tcl
===================================================================
--- trunk/base/src/macports1.0/macports.tcl	2014-08-17 19:01:31 UTC (rev 124046)
+++ trunk/base/src/macports1.0/macports.tcl	2014-08-17 19:09:55 UTC (rev 124047)
@@ -36,6 +36,8 @@
 package provide macports 1.0
 package require macports_dlist 1.0
 package require macports_util 1.0
+package require doctor 1.0
+package require reclaim 1.0
 package require Tclx
 
 namespace eval macports {
@@ -55,7 +57,7 @@
     variable user_options {}
     variable portinterp_options "\
         portdbpath porturl portpath portbuildpath auto_path prefix prefix_frozen portsharepath \
-        registry.path registry.format user_home \
+        registry.path registry.format user_home user_path \
         portarchivetype archivefetch_pubkeys portautoclean porttrace keeplogs portverbose destroot_umask \
         rsync_server rsync_options rsync_dir startupitem_type startupitem_install place_worksymlink macportsuser \
         configureccache ccache_dir ccache_size configuredistcc configurepipe buildnicevalue buildmakejobs \
@@ -658,6 +660,9 @@
         set macports::user_home /dev/null/NO_HOME_DIR
     }
 
+    # Save the path for future processing
+    set macports::user_path $env(PATH)
+
     # Configure the search path for configuration files
     set conf_files {}
     lappend conf_files ${macports_conf_path}/macports.conf
@@ -1189,6 +1194,9 @@
         }
     }
 
+    # Check the last time 'reclaim' was run
+    macports::check_last_reclaim
+
     # init registry
     set db_path [file join ${registry.path} registry registry.db]
     set db_exists [file exists $db_path]
@@ -4385,6 +4393,45 @@
     return yes
 }
 
+proc macports::doctor_main {opts} {
+    
+    # Calls the main function for the 'port doctor' command.
+    #
+    # Args: 
+    #           None
+    # Returns:
+    #           0 on successful execution.
+
+    doctor::main $opts
+    return 0
+}
+
+proc macports::check_last_reclaim {} {
+
+    # An abstraction layer for the reclaim function, 'check_last_run'.
+    #
+    # Args:
+    #           None
+    # Returns:
+    #           None
+
+    reclaim::check_last_run
+    return 0
+}
+
+proc macports::reclaim_main {} {
+
+    # Calls the main function for the 'port reclaim' command.
+    #
+    # Args:
+    #           None
+    # Returns:
+    #           None
+
+    reclaim::main
+    return 0
+}
+
 ##
 # Execute the rev-upgrade scan and attempt to rebuild all ports found to be
 # broken. Depends on the revupgrade_mode setting from macports.conf.

Copied: trunk/base/src/macports1.0/reclaim.tcl (from rev 124046, branches/gsoc14-cleanup/src/macports1.0/reclaim.tcl)
===================================================================
--- trunk/base/src/macports1.0/reclaim.tcl	                        (rev 0)
+++ trunk/base/src/macports1.0/reclaim.tcl	2014-08-17 19:09:55 UTC (rev 124047)
@@ -0,0 +1,383 @@
+# -*- coding: utf-8; mode: tcl; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- vim:fenc=utf-8:filetype=tcl:et:sw=4:ts=4:sts=4
+# reclaim.tcl
+# $Id: macports.tcl 119177 2014-04-18 22:35:29Z cal at macports.org $
+#
+# Copyright (c) 2002 - 2003 Apple Inc.
+# Copyright (c) 2004 - 2005 Paul Guyot, <pguyot at kallisys.net>.
+# Copyright (c) 2004 - 2006 Ole Guldberg Jensen <olegb at opendarwin.org>.
+# Copyright (c) 2004 - 2005 Robert Shaw <rshaw at opendarwin.org>
+# Copyright (c) 2004 - 2014 The MacPorts Project
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+# 3. Neither the name of Apple Inc. nor the names of its contributors
+#    may be used to endorse or promote products derived from this software
+#    without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+
+# TODO:
+
+# Finished:
+# Add ui_debug statments
+# Catch some error-prone areas.
+# Remove the useless/structure comments and add actual docstrings.
+# Add copyright notice
+# Check if inactive files are dependents for other files. 
+# Add test cases
+# Add distfile version checking.
+# Pretty sure we should be using ui_msg, instead of puts and what not. Should probably add that.
+# Register the "port cleanup" command with port.tcl and all that involves.
+# Implement a hash-map, or multidimensional array for ease of app info keeping. Write it yourself if you have to.
+# Figure out what the hell is going on with "port clean all" vs "port clean installed" the 'clean' target is provided by this package
+
+package provide reclaim 1.0
+
+package require registry_uninstall 2.0
+package require macports
+
+namespace eval reclaim {
+
+    proc main {args} {
+
+        # The main function. Calls each individual function that needs to be run.
+        # Args: 
+        #           None
+        # Returns:
+        #           None
+
+        uninstall_inactive
+        remove_distfiles
+        update_last_run
+    }
+
+    proc is_empty_dir {dir} {
+        
+        # Test if the given directory is empty.
+        # Args:
+        #           dir         - A string path of the given directory to test
+        # Returns:
+        #           0 if the directory is not empty, 1 if it is.
+
+        # Get _all_ files
+        set filenames [glob -nocomplain -tails -directory $dir * .*]
+
+        # Yay complex statements! Use RE, lsearch, and llength to determine if the directory is empty.  
+        expr {![llength [lsearch -all -not -regexp $filenames {^\.\.?$}]]}
+    }
+
+    proc walk_files {dir delete dist_paths} {
+
+        # Recursively walk through each directory that isn't an installed port and if delete each file that isn't a directory if requested.
+        # Args:
+        #           dir             - A string path of the given directory to walk through
+        #           delete          - Whether to delete each file found that isn't a directory or not. Set to 'yes' or 'no'. 
+        #           dist_paths      - A list of the full paths for all distfiles from installed ports  
+        # Returns: 
+        #           'no' if no distfiles were found, and 'yes' if distfiles were found. 
+
+        set found_distfile no 
+
+        # If the directory is empty, and this isn't the root folder, delete it and recursively go up directories until a non-empty one is found.
+        if { $dir ne "/opt/local/var/macports/distfiles" && [readdir $dir] eq ""} {
+
+            set up_dir [file dirname $dir]
+
+            ui_msg "Found empty directory: $dir. Attempting to delete."
+
+            if {[catch {file delete -force $dir} error] } {
+                ui_error "something went wrong when trying to delete $dir"
+            }
+
+            walk_files $up_dir $delete $dist_paths
+            return
+        }
+
+        foreach item [readdir $dir] {
+
+            set currentPath [file join $dir $item]
+
+            if {[file isdirectory $currentPath]} {
+
+                walk_files $currentPath $delete $dist_paths
+
+            } else {
+                
+                # If the current file isn't in the known-installed-distfiles
+                if {[lsearch $dist_paths $currentPath] == -1} {
+                    set found_distfile yes
+
+                    ui_msg "Found distfile: $item"
+
+                    if {$delete eq "yes"} {
+
+                        ui_debug "Deleting file: $item"
+                        ui_msg "Removing distfile: $item"
+
+                        if {[catch {file delete $currentPath} error]} {
+                            ui_error "something went wrong when trying to delete $currentPath"
+                        }
+
+                        # If the directory is now empty, recursively call on this directory, to delete it.
+                        if {[is_empty_dir $dir]} {
+
+                            ui_debug "Current directory is empty. Walking to $dir"
+                            walk_files $dir $delete $dist_paths
+                        }
+                    }
+                }
+            }
+        }
+
+        return $found_distfile
+    }
+
+    proc remove_distfiles {} {
+
+        # Check for distfiles in both the root, and home directories. If found, delete them.
+        # Args:
+        #               None
+        # Returns:
+        #               0 on successful execution
+
+        global macports::portdbpath
+        global macports::user_home
+
+        # The root and home distfile folder locations, respectively. 
+        set root_dist       [file join ${macports::portdbpath} distfiles]
+        set home_dist       ${macports::user_home}/.macports$root_dist
+
+        set port_info    [get_info]
+        set dist_path    [list]
+
+        foreach port $port_info {
+
+            set name        [lindex $port 0]
+            set version     [lindex $port 1]
+            set revision    [lindex $port 2]
+            set variants    [lindex $port 3]
+
+            # Get mport reference
+            if {[catch {set mport [mportopen_installed $name $version $revision $variants {}]} error]} {
+                ui_error "something went wrong when trying to get an mport reference."
+            }
+
+            # Setup sub-Tcl-interpreter that executed the installed port
+            set workername [ditem_key $mport workername]
+
+            # Append that port's distfiles to the list
+            set subdir [$workername eval return \$dist_subdir]
+            set name   [$workername eval return \$distfiles]
+
+            set root_path [file join $root_dist $subdir $name]
+            set home_path [file join $home_dist $subdir $name]
+
+            # Add the full file path to the list, depending where it's located.
+            if {[file isfile $root_path]} {
+                ui_debug "Appending $root_path."
+                lappend dist_path $root_path
+
+            } else {
+                if {[file isfile $home_path]} {
+                    ui_debug "Appending $home_path"
+                    lappend dist_path $home_path
+                }
+            }
+        }
+
+        ui_debug "Calling walk_files on root directory."
+
+        # Walk through each directory, and delete any files found. Alert the user if no files were found.
+        if {[walk_files $root_dist yes $dist_path] eq "no"} {
+            ui_msg "No distfiles found in root directory."
+        }
+
+        if {[file exists $home_dist]} {
+
+            ui_debug "Calling walk_files on home directory."
+
+            if {[walk_files $home_dist yes $dist_path] eq "no"} {
+                ui_msg "No distfiles found in home directory."
+            }
+        }
+
+        return 0
+    } 
+
+    proc close_file {file} {
+
+        # Closes the file, handling error catching if needed.
+        #
+        # Args: 
+        #           file - The file handler
+        # Returns:
+        #           None
+        if {[catch {close $file} error]} {
+            ui_error "something went wrong when closing file, $file."
+        }
+    }
+
+    proc is_inactive {app} {
+
+        # Determine's whether an application is inactive or not.
+        # Args: 
+        #           app - An array where the fourth item in it is the activity of the application.
+        # Returns:
+        #           1 if inactive, 0 if active.
+
+        if {[lindex $app 4] == 0} {
+            ui_debug "App, [lindex $app 0], is inactive."
+            return 1
+        }
+        ui_debug "App, [lindex $app 0], is not inactive."
+        return 0
+    }
+
+    proc get_info {} {
+
+        # Get's the information of all installed appliations (those returned by registry::installed), and returns it in a
+        # multidimensional list.
+        #
+        # Args:
+        #           None
+        # Returns:
+        #           A multidimensional list where each app is a sublist, i.e., [{First Application Info} {Second Application Info} {...}]
+        #           Indexes of each sublist are: 0 = name, 1 = version, 2 = revision, 3 = variants, 4 = activity, and 5 = epoch.
+        
+        if { [catch {set installed [registry::installed]} result]} {
+            ui_error "no installed applications found."
+        }
+
+        return $installed
+    }
+
+    proc update_last_run {} {
+        
+        # Updates the last_reclaim textfile with the newest time the code has been ran. 
+        #
+        # Args:
+        #           None
+        # Returns:
+        #           None
+
+        ui_debug "Updating last run information."
+
+        set path    [file join ${macports::portdbpath} last_reclaim.txt]
+        set fd      [open $path w]
+        puts $fd    [clock seconds]
+        close_file $fd
+    }
+
+    proc check_last_run {} {
+
+        # Periodically warn's the user that they haven't run 'port reclaim' in two weeks, and that they should consider doing so.
+        # 
+        # Args:
+        #           None
+        # Returns: 
+        #           None
+
+        ui_debug "Checking last run information."
+
+        set path [file join ${macports::portdbpath} last_reclaim.txt]
+
+        if {[file exists $path]} {
+
+            set fd      [open $path r]
+            set time    [gets $fd]
+            close_file $fd
+
+            if {$time ne ""} {
+                if {[clock seconds] - $time > 1209600} {
+                    ui_warn "you haven't run 'port reclaim' in two weeks. It's recommended you run this once every two weeks to help save space on your computer."
+                }
+            }
+        }
+    }
+
+    proc uninstall_inactive {} {
+
+        # Attempts to uninstall all inactive applications. (Performance is now O(N)!)
+        #
+        # Args: 
+        #           None
+        # Returns: 
+        #           0 if execution was successful. Errors (for now) if execution wasn't. 
+
+        set apps            [get_info]
+        set inactive_apps   [list]
+        set inactive_names  [list]
+        set inactive_count  0
+
+        ui_debug "Iterating through all inactive apps."
+
+        foreach app $apps {
+
+            if { [is_inactive $app] } {
+                lappend inactive_apps $app
+                lappend inactive_names [lindex $app 0]
+                incr inactive_count
+            }
+        }
+
+        if { $inactive_count == 0 } {
+            ui_msg "Found no inactive ports."
+
+        } else {
+
+            ui_msg "Found inactive ports: $inactive_names."
+            ui_msg "Would you like to uninstall these apps? \[Y/N\]: "
+
+            set input [gets stdin]
+            if {$input eq "Y" || $input eq "y" } {
+
+                ui_debug "Iterating through all inactive apps... again."
+
+                foreach app $inactive_apps {
+                    set name [lindex $app 0]
+
+                    # Get all dependents for the current application
+                    if {[catch {set dependents [registry::list_dependents $name [lindex 1] [lindex 2] [lindex 3]]} error]} {
+                        ui_error "something went wrong when trying to enumerate all dependents for $name"
+                    }
+                    if {dependents ne ""} {
+                        ui_warn "the following application ($name) is a dependent for $dependents. Are you positive you'd like to uninstall this 
+                                 (this could break other applications)? \[Y/N\]"
+
+                        set input [gets stdin]
+                        if { $input eq "N" || "n" } {
+                            ui_msg "Skipping application."
+                            continue
+                        }
+                    }
+                    ui_msg "Uninstalling: $name"
+
+                    # Note: 'uninstall' takes a name, version, revision, variants and an options list. 
+                    if {[catch {registry_uninstall::uninstall $name [lindex $app 1] [lindex $app 2] [lindex $app 3] {}} error]} {
+                        ui_error "something went wrong when uninstalling $name"
+                    }
+                }
+            } else {
+                ui_msg "Not uninstalling applications."
+            }
+        }
+        return 0
+    }
+}

Copied: trunk/base/src/macports1.0/tests/reclaim.test (from rev 124046, branches/gsoc14-cleanup/src/macports1.0/tests/reclaim.test)
===================================================================
--- trunk/base/src/macports1.0/tests/reclaim.test	                        (rev 0)
+++ trunk/base/src/macports1.0/tests/reclaim.test	2014-08-17 19:09:55 UTC (rev 124047)
@@ -0,0 +1,163 @@
+# -*- coding: utf-8; mode: tcl; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- vim:fenc=utf-8:ft=tcl:et:sw=4:ts=4:sts=4
+
+package require tcltest 2
+package require reclaim 1.0
+namespace import tcltest::*
+
+set pwd [file dirname [file normalize $argv0]]
+
+source ../macports_test_autoconf.tcl
+package require macports 1.0
+
+array set ui_options {}
+mportinit ui_options
+
+test is_empty_dir {
+
+    # Regression test for is_empty_dir.
+    # 
+    # Constraints:
+    #               None.
+
+    walk_files
+    Test for correctly identifying an empty directory.
+
+} -body {
+
+    set empty "emptyDir" 
+    file mkdir $empty 
+
+    if {[reclaim::is_empty_dir $empty] == 0} {
+        return "FAIL: Did not detect empty directory."
+    } 
+
+    return "Successfully detected empty directory."
+
+} -cleanup {
+    file delete -force $empty
+
+} -result "Successfully detected empty directory."
+
+test remove_distfiles {
+
+    # Regression test for remove_distfiles.
+    # 
+    # Constraints:
+    #               None.
+
+    Test for distfiles being successfully removed.
+
+} -body {
+    
+    set path [file join ${macports::portdbpath} distfiles]
+    set file [file join $path "test.txt"]
+
+    set fd   [open $file w]
+    close $fd
+    
+    reclaim::remove_distfiles
+
+    if {[file exists $file]} {
+        return "FAIL: Did not remove distfile."
+    }
+
+    return "Successfully removed distfile."
+
+} -cleanup {
+    file delete -force $file
+
+} -result "Successfully removed distfile."
+
+test update_last_run {
+
+    # Regression test for update_last_run.
+    # 
+    # Constraints:
+    #               Require's root to run. 
+
+    Tests for last_reclaim.txt being updated.
+
+} -constraints {
+    root
+
+} -body {
+
+    set path     [file join ${macports::portdbpath} last_reclaim.txt]
+
+    set fd          [open $path w]
+    close $fd
+
+    set fd          [open $path r]
+    set old_time    [gets $fd]
+    close $fd
+
+    reclaim::update_last_run
+
+    set fd          [open $path r]
+    set new_time    [gets $fd]
+    close $fd
+
+    if {$new_time == $old_time} {
+        return "FAIL: Did not update to the current time."
+    }
+
+    return "Successfully updated to the correct time."
+
+} -cleanup {
+    set fd  [open $path w]
+    puts $fd $old_time
+    close $fd
+
+} -result "Successfully updated to the correct time."
+
+
+test walk_files {
+
+    # Regression test for walk_files.
+    # 
+    # Constraints:
+    #               Require's root to run. 
+
+    Tests if walking through the files, and deleting distfiles, ignoring normal files, and removing directory trees works.
+
+} -constraints {
+    root
+
+} -body {
+    
+    set path        [file join ${macports::portdbpath} distfiles]
+    set dir         [file join $path tmp_dir]
+    set subdir      [file join $dir other_tmp_dir]
+    set bad_dist    [file join $subdir bad_distfile.txt]
+    set bad_dist2   [file join $dir bad_distfile2.txt]
+    set good_dist   [file join $dir good_distfile.txt]
+    set dist_list   [list]
+
+    lappend dist_list $good_dist
+
+    file mkdir $subdir
+
+    set $fd         [open $bad_dist w] 
+    close $fd
+
+    set $fd         [open $bad_dist2 w] 
+    close $fd
+
+    set $fd         [open $good_dist w] 
+    close $fd
+
+    reclaim::walk_files $dir yes $dist_list 
+
+    if {[file exists $bad_dist] || [file exists $bad_dist2] || [file exists $subdir] || ![file exists $good_dist] || ![file exists $dir]} {
+        return "FAIL: Did not delete the correct files, or deleted files that should not have been deleted."
+    }
+
+    return "Successfully deleted all files that needed to be deleted."
+    
+} -cleanup {
+    file delete -force $dir  
+
+} -result "Successfully deleted all files that needed to be deleted."
+
+cleanupTests
+

Modified: trunk/base/src/port/port.tcl
===================================================================
--- trunk/base/src/port/port.tcl	2014-08-17 19:01:31 UTC (rev 124046)
+++ trunk/base/src/port/port.tcl	2014-08-17 19:09:55 UTC (rev 124047)
@@ -43,6 +43,7 @@
     set portclient::progress::hasTermAnsiSend yes
 }
 
+package require Tclx
 package require macports
 package require Pextlib 1.0
 
@@ -2725,7 +2726,23 @@
     return $status
 }
 
+proc action_doctor { action portlist opts } {
+    if {[prefix_unwritable]} {
+        return 1
+    }
+    macports::doctor_main $opts
+    return 0
+}
 
+proc action_reclaim { action portlist opts } {
+    if {[prefix_unwritable]} {
+        return 1
+    }
+    macports::reclaim_main  
+    return 0
+}
+
+
 proc action_upgrade { action portlist opts } {
     if {[require_portlist portlist "yes"] || ([prefix_unwritable] && ![macports::global_option_isset ports_dryrun])} {
         return 1
@@ -4205,6 +4222,8 @@
     \
     upgrade     [list action_upgrade        [ACTION_ARGS_PORTS]] \
     rev-upgrade [list action_revupgrade     [ACTION_ARGS_NONE]] \
+    reclaim     [list action_reclaim        [ACTION_ARGS_NONE]] \
+    doctor      [list action_doctor         [ACTION_ARGS_NONE]] \
     \
     version     [list action_version        [ACTION_ARGS_NONE]] \
     platform    [list action_platform       [ACTION_ARGS_NONE]] \
@@ -4364,6 +4383,7 @@
     log         {{phase 1} {level 1}}
     upgrade     {force enforce-variants no-replace no-rev-upgrade}
     rev-upgrade {id-loadcmd-check}
+    doctor      {quiet}
 }
 
 ##
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.macosforge.org/pipermail/macports-changes/attachments/20140817/afa88da2/attachment-0001.html>


More information about the macports-changes mailing list