On 20.03.2008 16:46, Adam Boyle wrote:
> I'm looking for a simple way to use Find.find to produce a list of
> files/directories for NSIS.  Ideally the list will sort files before
> directories so as to minimize the number of times SetOutPath is used
> (an NSIS function).
> 
> The script so far is as follows:
> -----------snip-----------------------
> dirs = ["jruby-1.0.3"]
> excludes = []
> for dir in dirs
>   folder = ''
>   Find.find(dir) do |path|
>     if FileTest.directory?(path)
>       if excludes.include?(File.basename(path))
>         Find.prune       # Don't look any further into this directory.
>       else
>         next
>       end
>     else
>       if folder != File.dirname(path)
>         folder = File.dirname(path)
>         puts 'SetOutPath "' + folder + '"'
>       end
>       puts 'File       "' + path + '"'
>     end
>   end
> end
> 
> -----------------------end snip-------------------
> 
> Simple directory traversal, no problem there.  The issue is that
> Find.find doesn't allow any sort of ordering to be specified; namely
> that directories are mixed in with files.  The script produces the
> following output:
> 
> ---------------output---------------------------------
> SetOutPath "jruby-1.0.3/docs"
> File       "jruby-1.0.3/docs/README.rails"
> File       "jruby-1.0.3/docs/README.coverage"
> File       "jruby-1.0.3/docs/Readline-HOWTO.txt"
> SetOutPath "jruby-1.0.3/docs/rbyaml"
> File       "jruby-1.0.3/docs/rbyaml/README"
> File       "jruby-1.0.3/docs/rbyaml/LICENSE"
> SetOutPath "jruby-1.0.3/docs"
> File       "jruby-1.0.3/docs/LICENSE.bouncycastle"
> File       "jruby-1.0.3/docs/LICENSE.ant"
> File       "jruby-1.0.3/docs/LICENCE.bsf"
> SetOutPath "jruby-1.0.3/docs/jvyaml"
> File       "jruby-1.0.3/docs/jvyaml/README"
> File       "jruby-1.0.3/docs/jvyaml/LICENSE"
> File       "jruby-1.0.3/docs/jvyaml/CREDITS"
> SetOutPath "jruby-1.0.3/docs"
> File       "jruby-1.0.3/docs/Glossary.txt"
> File       "jruby-1.0.3/docs/getting_involved.html"
> -----------------------end output-------------------------
> 
> The desired output would sort sub-folders before files when traversing
> a given directory, thus eliminating the duplicate entries for
> SetOutPath "jruby-1.0.3/docs" as seen above.
> 
> ------------desired output--------------------------------
> SetOutPath "jruby-1.0.3/docs"
> File       "jruby-1.0.3/docs/README.rails"
> File       "jruby-1.0.3/docs/README.coverage"
> File       "jruby-1.0.3/docs/Readline-HOWTO.txt"
> File       "jruby-1.0.3/docs/LICENSE.bouncycastle"
> File       "jruby-1.0.3/docs/LICENSE.ant"
> File       "jruby-1.0.3/docs/LICENCE.bsf"
> File       "jruby-1.0.3/docs/Glossary.txt"
> File       "jruby-1.0.3/docs/getting_involved.html"
> SetOutPath "jruby-1.0.3/docs/rbyaml"
> File       "jruby-1.0.3/docs/rbyaml/README"
> File       "jruby-1.0.3/docs/rbyaml/LICENSE"
> SetOutPath "jruby-1.0.3/docs/jvyaml"
> File       "jruby-1.0.3/docs/jvyaml/README"
> File       "jruby-1.0.3/docs/jvyaml/LICENSE"
> File       "jruby-1.0.3/docs/jvyaml/CREDITS"
> ------------------------------end output--------------------------
> 
> Any ideas?

IIRC Find.find does sort sub folders before files.  To me your code 
seems pretty complex and I believe the major problem is that you check 
the same directory over and over again for exclusion because you use 
File.basename.  Can't you just do this?

Find.find base do |path|
   if File.directory? path
     if excludes.include? path
       Find.prune
     else
       puts "SetOutPath #{path}"
     end
   else
     puts "File #{path}"
   end
end

Kind regards

	robert