Commits

Anonymous committed f4a6fd3

Restore the ability to dock a plain tarball or zipball.

Comments (0)

Files changed (2)

 
     toolshelf dock https://bitbucket.org/plato/the-republic
 
-will clone a Mercurial repo from Bitbucket.  And you can dock a vanilla,
+will clone a Mercurial repo from Bitbucket.  And you can dock a vanilla,
 non-version-controlled tarball by saying
 
     toolshelf dock http://example.com/distfiles/foo-1.0.tar.gz
 
-(It will place the source tree in a directory called `example.com/foo-1.0`
-under `$TOOLSHELF`.)
+(It will download the tarball to `$TOOLSHELF/.distfiles/foo-1.0.tar.gz`
+and cache it there, extract it to a temporary directory, and place the
+source tree in `$TOOLSHELF/example.com/distfile/foo-1.0`.  This will work
+regardless of whether the tarball contains a single directory called
+`foo-1.0`, as is standard, or if it is a "tarbomb" where all the files are
+contained in the root of the tar archive.  Which is frowned upon.)
 
 `toolshelf` understands a few shortcuts for Github and Bitbucket:
 
 
     gh:user/project
       exclude_path tests
-      build_command ./configure --with-lighter-fluid --no-barbecue
+      build_command ./configure --with-lighter-fluid --no-barbecue && make
 
 It should be possible to have a local cookies files that supplements
 `toolshelf`'s supplied cookies file, at some point.
     
 *   ♦ `prerequisite`
     
-    Example: `prerequisite gh:nelhage/reptyr`
+    Example: `prerequisite gh:Scriptor/Pharen`
     
     indicates a dependency source tree.  When this is given, `toolshelf`
     first checks if you have the source named by the hint's value, a source
     specification, docked; if you do not, it will try to dock that source first.
-    Example: `d=Scriptor/Pharen`.
     
 *   ♦ `exclude_path`
     
     following directories from being put on the path: `tests/x86/passing`,
     `tests/x86/failing`, `tests/x8600`.
     
-*   ♦ `o`
+*   ♦ `only_path`
+    
+    Example: `only_path bin`
     
     indicates that *only* these subdirectories should be added to the
-    executable search path.  Example: `o=bin`.
+    executable search path.
     
 *   ♦ `build_command`
     
-    specifies a command to run to build the source.  Not sure if it will
-    be passed to a shell for execution, or just split into words at the spaces.
-    The command will be run with the root of the source tree as the working
-    directory.  Note that if the command contains spaces, and the source spec
-    is given on the command line, it will need to be quoted.
-    Example: `b=tools/make-it`.
+    Example: `build_command ./configure --no-cheese && make`
+    
+    specifies a command to run to build the source.  Passes the entire hint
+    value to the shell for execution.  The command will be run with the root
+    of the source tree as the working directory. 
 
 Theory of Operation
 -------------------
   being put on your path (because they have rather generic names, and are
   probably not things that you would use frequently.)
 
-* ♦ `toolshelf dock `[`http://ftp.gnu.org/gnu/bison/bison-2.5.tar.gz`][]
+* `toolshelf dock `[`http://ftp.gnu.org/gnu/bison/bison-2.5.tar.gz`][]
 
-  ♦ `{x=tests:x=etc:x=examples:x=build-aux}`
   Is your system `bison` version 2.4, but you need version 2.5 installed
   temporarily in order to build `kulp/tenyr`?  No problem; just put it on
   your `toolshelf` with the above command.  After it's docked, you can issue
   the commands `toolshelf path disable ftp.gnu.org/bison-2.5` and
   `toolshelf path rebuild ftp.gnu.org/bison-2.5` to remove or reinstate
   it from your search path, respectively.
+  TODO ♦ `{x=tests:x=etc:x=examples:x=build-aux}`
 
 [`gh:nelhage/reptyr`]: https://github.com/nelhage/reptyr
-[`bb:catseye/yucca`] https://bitbucket.org/catseye/yucca
+[`bb:catseye/yucca`]: https://bitbucket.org/catseye/yucca
 [`gh:kulp/tenyr`]: https://github.com/kulp/tenyr
 [`http://ftp.gnu.org/gnu/bison/bison-2.5.tar.gz`]: http://www.gnu.org/software/bison/bison.html
 
     subprocess.check_call(args)
 
 
+def chdir(path):
+    note("* Changing dir to `%s`..." % path)
+    os.chdir(path)
+
+
 def note(msg):
     if OPTIONS.verbose:
         print msg
         self.type = type
         self.hints = hints
 
+    def __repr__(self):
+        return ("Source(url=%r, host=%r, user=%r, "
+                "project=%r, type=%r, hints=%r)" %
+                (self.url, self.host, self.user,
+                 self.project, self.type, self.hints))
+
     @classmethod
     def from_catalog(klass, filename, problems):
         filename = os.path.join(CWD, filename)
     @property
     def distfile(self):
         if self.type in ('zip', 'tgz', 'tar.gz'):
-            return os.path.join(self.dir, '%s.%s' % (self.project, self.type))
+            return os.path.join(TOOLSHELF, '.distfiles',
+                                '%s.%s' % (self.project, self.type))
         else:
             return None
 
                 pass
             else:
                 raise
-        os.chdir(self.user_dir)
+        chdir(self.user_dir)
 
         if self.type == 'git':
             run('git', 'clone', self.url)
         elif self.type == 'hg':
             run('hg', 'clone', self.url)
         elif self.distfile is not None:
-            # XXX might not work anymore
-            run('rm', '-f', self.distfile)
-            run('wget', '-nc', '-O', self.distfile, self.url)
+            run('mkdir', '-p', os.path.join(TOOLSHELF, '.distfiles'))
+            if not os.path.exists(self.distfile):
+                run('wget', '-nc', '-O', self.distfile, self.url)
             extract_dir = os.path.join(
-                self.dir, '.extract_' + self.project
+                TOOLSHELF, '.extract_' + self.project
             )
             run('mkdir', '-p', extract_dir)
-            os.chdir(extract_dir)
+            chdir(extract_dir)
             if self.type == 'zip':
                 run('unzip', self.distfile)
             elif self.type in ('tgz', 'tar.gz'):
 
             files = os.listdir(extract_dir)
             if len(files) == 1:
+                note("Archive is well-structured "
+                     "(all files in one directory)")
                 extracted_dir = os.path.join(extract_dir, files[0])
                 if not os.path.isdir(extracted_dir):
                     extracted_dir = extract_dir
             else:
+                note("Archive is a 'tarbomb' "
+                     "(all files in the root of the archive)")
                 extracted_dir = extract_dir
             run('mv', extracted_dir, self.dir)
             run('rm', '-rf', extract_dir)
             return
         note("* Building %s..." % self.dir)
 
-        os.chdir(self.dir)
+        chdir(self.dir)
         if os.path.isfile('build.sh'):
             run('./build.sh')
         else:
             if os.path.isfile('Makefile'):
                 run('make')
             elif os.path.isfile('src/Makefile'):
-                os.chdir('src')
+                chdir('src')
                 run('make')
 
     def update(self):
-        os.chdir(self.dir)
+        chdir(self.dir)
         if os.path.isdir('.git'):
             run('git', 'pull')
         if os.path.isdir('.hg'):
         print "Usage: " + __doc__
         sys.exit(2)
 
-    os.chdir(TOOLSHELF)
+    chdir(TOOLSHELF)
     result = LazyFile(RESULT_SH_FILENAME)
     CONFIG = Config()
     COOKIES = Cookies()