purplepkg 0.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/bin/install_ruby ADDED
@@ -0,0 +1,49 @@
1
+ #!/bin/bash
2
+
3
+ if [ -z "$1" ]; then
4
+ echo "Usage: $0 ruby-<version>.tar.gz"
5
+ exit 1
6
+ fi
7
+
8
+ if [ ! -f "$1" ]; then
9
+ echo "File does not exist: $1"
10
+ exit 1
11
+ fi
12
+
13
+ if [ ! -f 'purple.gemspec' ]; then
14
+ echo "Please only run this script from purple source directory."
15
+ exit 1
16
+ fi
17
+
18
+ rm -f install_ruby.log
19
+ export TARBALL=$1
20
+ export PURPLE_TOPDIR=`pwd`
21
+
22
+ function system() {
23
+ echo -n "$1" >&2
24
+ shift
25
+ $* >> $PURPLE_TOPDIR/install_ruby.log 2>&1
26
+ STATUS=$?
27
+ echo >&2
28
+ if [ 0 -ne $STATUS ]; then
29
+ echo "Error ocurred. Please check install_ruby.log."
30
+ fi
31
+ }
32
+
33
+ # Determine ruby topdir
34
+ export RUBY_TOPDIR=/tmp/`tar tzf "$TARBALL" | head -1`
35
+
36
+ # Extract source
37
+ system "Extracting source..." tar -C /tmp xzf $TARBALL
38
+
39
+ cd $RUBY_TOPDIR
40
+
41
+ # Compile ruby
42
+ system "Configuring..." ./configure
43
+ system "Building..." make
44
+
45
+ # Run purple to stage ruby package
46
+ $RUBY_TOPDIR/miniruby -I lib -I "$RUBY_TOPDIR"/lib bin/purple -i $TARBALL
47
+
48
+ # Clean /tmp
49
+ rm -fr "$RUBY_TOPDIR"
data/bin/purple ADDED
@@ -0,0 +1,141 @@
1
+ #!/usr/bin/ruby -w
2
+
3
+ require 'uri'
4
+ require 'uri/http'
5
+ require 'getoptlong'
6
+
7
+ require 'purple'
8
+
9
+ def usage
10
+ puts <<-EOS
11
+ Purple Packager, Copyright (c) 2004, Simon Conrad-Armes <curne@curnomatic.dk>
12
+ Rights granted, under GNU GPL (version 2 or later), see file LICENSE
13
+
14
+ Usage: #{File.basename $0} [options] <package>
15
+
16
+ Options:
17
+ --make Make a package from the staged install.
18
+ -m
19
+ --deploy Deploy the built package. Implies --make.
20
+ -i
21
+ --skip-to=step Skip to the given step [prepare].
22
+ --stop-at=step Stop after given step is complete [build].
23
+ --manual Print the manual page for Purple Package.
24
+
25
+ The arguments given to --skip-to and --stop-at must be one of
26
+ 'prepare', 'build', 'stage', or 'deps'.
27
+
28
+ <package>
29
+ The package argument may be a url or path to a local file path. The file
30
+ ending determines how it is handled:
31
+ .tar.gz Source Tarball assumed. A purple spec is created
32
+ inferring the name and version from the filename.
33
+ .purple Purple spec script. Contains references to source and
34
+ build instructions.
35
+ .purple-src Purple source package. Contains source files and build
36
+ instructions.
37
+ .purple-bin Purple binary package.
38
+
39
+ EOS
40
+ exit 1
41
+ end
42
+
43
+ def filetype url
44
+ filename = File.basename(URI.parse(url).path)
45
+ return case filename
46
+ when /\.tar\.(gz|bz2)|\.tgz$/
47
+ :tarball
48
+ when /\.purple$/
49
+ :script
50
+ end
51
+ end
52
+
53
+ ALL_STEPS = { :prepare => 0, :build => 2, :stage => 4, :deps => 6 }
54
+
55
+
56
+ usage if 0 == ARGV.size
57
+
58
+ opts = GetoptLong.new
59
+ opts.set_options(
60
+ [ '--help', GetoptLong::OPTIONAL_ARGUMENT],
61
+ [ '--make', '-m', GetoptLong::NO_ARGUMENT],
62
+ [ '--deploy', '-i', GetoptLong::NO_ARGUMENT],
63
+ [ '--skip-to', GetoptLong::REQUIRED_ARGUMENT],
64
+ [ '--stop-at', GetoptLong::REQUIRED_ARGUMENT],
65
+ [ '--manual', GetoptLong::REQUIRED_ARGUMENT]
66
+ )
67
+
68
+ OPTIONS = Hash.new
69
+ opts.each_option { |name,arg| OPTIONS[name.gsub(/^--/, '')] = arg }
70
+ p OPTIONS
71
+
72
+ usage if OPTIONS.has_key? 'help'
73
+
74
+ steps = [:prepare, :config, :build, :stage]
75
+
76
+ if OPTIONS.has_key? 'make' or 'deps' == OPTIONS['stop-at']
77
+ steps << :deps
78
+ end
79
+
80
+ if OPTIONS.has_key? 'skip-to'
81
+ if 'make' == OPTIONS['skip-to']
82
+ first = steps.size
83
+ else
84
+ first = steps.index OPTIONS['skip-to'].intern
85
+ end
86
+ else
87
+ first = 0
88
+ end
89
+
90
+ if OPTIONS.has_key? 'stop-at'
91
+ last = steps.index OPTIONS['stop-at'].intern
92
+ else
93
+ last = steps.size - 1
94
+ end
95
+
96
+ steps = steps[first..last]
97
+
98
+
99
+ # Convert local paths to urls
100
+ arg_ref = ARGV[0]
101
+ arg_uri = URI.parse(arg_ref)
102
+ if not arg_uri.scheme
103
+ arg_uri.scheme = 'file'
104
+ arg_uri.path = File.join(Dir.pwd, arg_uri.path) if arg_uri.path !~ %r"^/"
105
+ end
106
+ arg_ref = arg_uri.to_s
107
+
108
+ # Decide what to do with the argument
109
+ puts "DEBUG main: #{filetype(arg_ref).inspect}"
110
+ case filetype(arg_ref)
111
+ when :tarball
112
+ @cabinet = Purple.cabinet_from_url arg_ref
113
+ when :script
114
+ @cabinet = Purple::Script.open URI.parse(arg_ref).path
115
+ else
116
+ raise "Unknown file type of argument '#{arg_ref}'"
117
+ end
118
+ p @cabinet
119
+
120
+ error = catch :stop do
121
+ @cabinet.setup
122
+
123
+ @cabinet.run_steps steps
124
+
125
+ if OPTIONS.has_key? 'make' or OPTIONS.has_key? 'deploy'
126
+ Purple::Platform.detect
127
+ @cabinet.make
128
+ end
129
+
130
+ if OPTIONS.has_key? 'deploy'
131
+ puts "DEBUG: Doing deploy"
132
+ @cabinet.deploy
133
+ end
134
+
135
+ :normal_complete
136
+ end
137
+
138
+ if :normal_complete != error
139
+ STDERR.puts "An error condition was encountered and forced a stop."
140
+ STDERR.puts "Reason: #{error}" if error
141
+ end
@@ -0,0 +1,34 @@
1
+ require 'uri'
2
+
3
+ module Purple
4
+ module Getter
5
+ def self.new url, destdir
6
+ puts "DEBUG Getter##new: url=#{url}"
7
+ @uri = URI.parse url
8
+ plugin = case @uri.scheme
9
+ when /http|ftp/
10
+ 'wget'
11
+ when 'file'
12
+ 'cp'
13
+ else
14
+ raise StandardError.new("Unable to handle scheme #{@uri.scheme}")
15
+ end
16
+ require "purple/getter_#{plugin}"
17
+ (eval "Purple::Getter::Getter_#{plugin}").new @uri, destdir
18
+ end
19
+
20
+ class Generic
21
+ # -> anIO
22
+ def initialize uri, destdir
23
+ self.uri = uri
24
+ @status = 'Getting'
25
+ @destdir = destdir
26
+ end
27
+ attr_accessor :uri, :length, :content_type
28
+ attr_reader :thread
29
+
30
+ # def get -> nil
31
+ # def get_status -> anArray [status, %done]
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,22 @@
1
+ require 'open3'
2
+
3
+ module Purple
4
+ module Getter
5
+ class Getter_cp < Generic
6
+ def get
7
+ if system "ln '#{@uri.path}' '#{@destdir}/'"
8
+ @done = '100'
9
+ @status = 'Done'
10
+ else
11
+ @done = '100'
12
+ @status = 'Error'
13
+ end
14
+ end
15
+
16
+ def get_status
17
+ [@status, @done]
18
+ end
19
+
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,105 @@
1
+ require 'open3'
2
+
3
+ module Purple
4
+ module Getter
5
+ class Getter_wget < Generic
6
+ def initialize *args
7
+ super
8
+ @done = "0"
9
+ end
10
+
11
+ def get
12
+ @thread = Thread.new do
13
+ filename = File.basename uri.path
14
+ Open3.popen3 "wget --progress dot -O '#{@destdir}/#{filename}' #{@uri.to_s} 2>&1" do
15
+ |pw, pr, pe|
16
+ parse_input pw, pr, pe
17
+ end
18
+ end
19
+ end
20
+
21
+ def get_status
22
+ [@status, @done]
23
+ end
24
+
25
+ # wget specific methods
26
+
27
+ def parse_input pw, pr, pe
28
+ #puts "DEBUG Getter_wget#parse_input: Start"
29
+
30
+ loop do
31
+ # Start line
32
+ 2.times { pr.gets }
33
+
34
+ # Host lookup
35
+ #puts "DEBUG Getter_wget#parse_input: Host lookup"
36
+ line = pr.gets
37
+ #puts "->#{line}"
38
+ if line =~ /failed:/
39
+ @status = 'Host lookup failed'
40
+ return
41
+ end
42
+
43
+ # Connecting
44
+ #puts "DEBUG Getter_wget#parse_input: Connecting"
45
+ line = pr.gets
46
+ #puts "->#{line}"
47
+ md = /^Connecting to (.*?)... (.*?)$/.match line
48
+ #puts "DEBUG Getter_wget#parse_input: md[2]=#{md[2].inspect}"
49
+
50
+ unless 'connected.' == md[2]
51
+ @status = 'Connection failed'
52
+ return
53
+ end
54
+
55
+ # Request
56
+ #puts "DEBUG Getter_wget#parse_input: Sending request"
57
+ line = pr.gets
58
+ #puts "->#{line}"
59
+ md = /HTTP request sent, awaiting response... (.*)/.match line
60
+ case md[1]
61
+ when '200 OK'
62
+ # Okay. Continue
63
+ when /^3\d{2}/
64
+ # Redirection
65
+ pr.gets # Location line
66
+ redo
67
+ else
68
+ @status = md[1]
69
+ return
70
+ end
71
+
72
+ break
73
+ end
74
+
75
+ # Content details
76
+ line = pr.gets
77
+ #puts "->#{line}"
78
+ md = /Length: (.*?) \[(.*?)\]/.match line
79
+ @length = md[1].gsub(',', '').to_i
80
+ @content_type = md[2]
81
+
82
+ # Empty line
83
+ pr.gets
84
+
85
+ # Data incoming
86
+ pr.each do |line|
87
+ #puts "->#{line}"
88
+
89
+ md = / *([0-9]+)K[ \.]+([0-9]+)% +([0-9\.,]+ KB\/s)/.match line
90
+ #puts (md ? "DEBUG #{md.to_a.inspect}" : "DEBUG nil")
91
+ if md
92
+ @done = md[2]
93
+ @rate = md[3]
94
+ next
95
+ end
96
+
97
+ if "100" == @done
98
+ @status = "Done"
99
+ end
100
+ pr.read
101
+ end
102
+ end
103
+ end
104
+ end
105
+ end
@@ -0,0 +1,59 @@
1
+
2
+ module Purple
3
+
4
+ # Makefile aware predicate container. Initialize with path
5
+ # to source directory.
6
+ class MakefileMaven
7
+ def initialize srcdir
8
+ @srcdir = srcdir
9
+ end
10
+
11
+ def has_makefile?
12
+ makefilename && true
13
+ end
14
+
15
+ def makefilename
16
+ return @makefilename if defined? @makefilename
17
+ @makefilename = ['GNUmakefile', 'makefile', 'Makefile'].find do |name|
18
+ puts "DEBUG MakefileMaven#makefilename: testing #{File.join(@srcdir, name)}"
19
+ FileTest.exist? File.join(@srcdir, name)
20
+ end
21
+ end
22
+
23
+ def uses_prefix?
24
+ return true if makefile_rules.grep(/^prefix/).size > 0
25
+ false
26
+ end
27
+
28
+ def uses_destdir?
29
+ return true if makefile_rules.grep(/DESTDIR/).size > 0
30
+ false
31
+ end
32
+
33
+ def makefile_rules
34
+ return @rules if defined? @rules
35
+ @rules = `make -pn -C #{@srcdir}`
36
+ end
37
+
38
+ def makefile_contents
39
+ return @contents if defined? @contents
40
+
41
+ @contents = ''
42
+ files = [makefilename];
43
+ while files.size > 0
44
+ filename = File.join(@srcdir, files.shift)
45
+ if FileTest.exist? filename
46
+ puts "DEBUG MakefileMaven#makefile_contents: loop->if"
47
+ text = File.open(filename) { |f| f.read }
48
+ @contents << text
49
+ text.grep(/^include /).each do |s|
50
+ md = /^include (.*?)\n$/.match s
51
+ files << md[1]
52
+ end
53
+ end
54
+ end
55
+ puts "DEBUG MakefileMaven#makefile_contents: #{@contents.to_a.size} lines"
56
+ @contents
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,20 @@
1
+
2
+ module Purple
3
+
4
+ module Matches
5
+ EXTENSIONS = '(\.tar\.gz|\.tar\.bz2|\.tgz|\.zip)'
6
+ REGEXPS = [
7
+ /^(.+)-((\d+)(\.\d+)*(-?\w+)?)#{EXTENSIONS}$/,
8
+ /^(.+)\.([^\.]+?)#{EXTENSIONS}$/,
9
+ ];
10
+
11
+ def self.match_filename filename
12
+ md = nil
13
+ REGEXPS.find { |r| md = r.match filename }
14
+ #puts "DEBUG Matches#match_filename: filename=#{filename.inspect} md=#{md.to_a.inspect}"
15
+ raise 'filename does not match pattern' if not (md and not md.to_a[0..1].include? nil)
16
+
17
+ { :name => md[1], :version => md[2] }
18
+ end
19
+ end
20
+ end
data/lib/purple/osx.rb ADDED
@@ -0,0 +1,117 @@
1
+
2
+ module Purple
3
+
4
+ PACKAGE_DESCRIPTION_TEMPLATE = proc do |pkg| <<EOS
5
+ <?xml version="1.0" encoding="UTF-8"?>
6
+ <!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
7
+ <plist version="1.0">
8
+ <dict>
9
+ <key>IFPkgDescriptionTitle</key>
10
+ <string>#{pkg.name}</string>
11
+ <key>IFPkgDescriptionVersion</key>
12
+ <string>#{pkg.version}</string>
13
+ </dict>
14
+ </plist>
15
+ EOS
16
+ end
17
+
18
+
19
+ PACKAGE_INFO_TEMPLATE = proc do |pkg| <<EOS
20
+ <?xml version="1.0" encoding="UTF-8"?>
21
+ <!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
22
+ <plist version="1.0">
23
+ <dict>
24
+ <!--
25
+ <key></key>
26
+ <string></string>
27
+ ***
28
+ -->
29
+ <key>CFBundleGetInfoString</key>
30
+ <string>#{pkg.info_string}</string>
31
+ <key>CFBundleIdentifier</key>
32
+ <string>#{pkg.identifier}</string>
33
+ <key>CFBundleName</key>
34
+ <string>#{pkg.name}</string>
35
+ <key>CFBundleShortVersionString</key>
36
+ <string>#{pkg.version}</string>
37
+ <key>IFMajorVersion</key>
38
+ <integer>#{pkg.major}</integer>
39
+ <key>IFMinorVersion</key>
40
+ <integer>#{pkg.minor}</integer>
41
+ <key>IFPkgFlagAllowBackRev</key>
42
+ <false/>
43
+ <key>IFPkgFlagAuthorizationAction</key>
44
+ <string>AdminAuthorization</string>
45
+ <key>IFPkgFlagDefaultLocation</key>
46
+ <string>/</string>
47
+ <key>IFPkgFlagInstallFat</key>
48
+ <false/>
49
+ <key>IFPkgFlagIsRequired</key>
50
+ <false/>
51
+ <key>IFPkgFlagOverwritePermissions</key>
52
+ <true/>
53
+ <key>IFPkgFlagRelocatable</key>
54
+ <false/>
55
+ <key>IFPkgFlagRestartAction</key>
56
+ <string>NoRestart</string>
57
+ <key>IFPkgFlagRootVolumeOnly</key>
58
+ <true/>
59
+ <key>IFPkgFlagUpdateInstalledLanguages</key>
60
+ <false/>
61
+ <key>IFPkgFlagUseUserMask</key>
62
+ <false/>
63
+ <key>IFPkgFormatVersion</key>
64
+ <real>0.10000000149011612</real>
65
+ </dict>
66
+ </plist>
67
+ EOS
68
+ end
69
+
70
+ class PackageInfo
71
+ def info_string; long_name; end
72
+ end
73
+
74
+ class PurpleCabinet
75
+ def osx_stage
76
+ assert_dir "#{@cabinet_dir}"
77
+ assert_dir "#{@cabinet_dir}/OsxStage"
78
+ assert_dir File.join(@cabinet_dir, 'OsxStage')
79
+ end
80
+
81
+ def make
82
+ packages.each do |pkg|
83
+ system "rm -r '#{osx_stage}'"
84
+ File.open "#{osx_stage}/Description.plist", "w" do |f|
85
+ f.puts pkg.description
86
+ end
87
+
88
+ Dir.mkdir "#{osx_stage}/Resources"
89
+ File.open "#{osx_stage}/Resources/Welcome.txt", "w" do |f|
90
+ f.print <<-EOS
91
+ Hello, World!
92
+ EOS
93
+ end
94
+
95
+ File.open "#{osx_stage}/Info.plist", "w" do |f|
96
+ f.print PACKAGE_INFO_TEMPLATE.call(pkg)
97
+ end
98
+
99
+ File.open "#{osx_stage}/Description.plist", "w" do |f|
100
+ f.print PACKAGE_DESCRIPTION_TEMPLATE.call(pkg)
101
+ end
102
+
103
+ system "/Developer/Applications/Utilities/PackageMaker.app/Contents/MacOS/PackageMaker " +
104
+ "-build -p '#{packagedir}/#{pkg.name}.pkg' -f '#{pkg.stage_root}' -r '#{osx_stage}/Resources' " +
105
+ "-d '#{osx_stage}/Description.plist' -i '#{osx_stage}/Info.plist'"
106
+ end
107
+ end
108
+
109
+
110
+ def deploy
111
+ packages.each do |pkg|
112
+ system "open '#{File.join packagedir, pkg.name}.pkg'"
113
+ end
114
+ end
115
+ end
116
+
117
+ end
@@ -0,0 +1,95 @@
1
+
2
+ module Purple
3
+ module PackageActions
4
+
5
+ attr_accessor :cabinet
6
+
7
+ def self.package_method name
8
+ prg = <<-EOS
9
+ def #{name}
10
+ if defined? @method_#{name}_package and @method_#{name}_package
11
+ return @method_#{name}_package.call(self)
12
+ else
13
+ m = self.method "default_#{name}"
14
+ return(m.call) if m
15
+ end
16
+ end
17
+ def #{name}= prc
18
+ @method_#{name}_package = prc
19
+ end
20
+ EOS
21
+ #puts prg
22
+ module_eval prg
23
+ end
24
+
25
+ def srcdir
26
+ return @srcdir if defined? @srcdir
27
+ dirs = Dir.new(cabinet.srcdir).reject { |s| s =~ /^\.{1,2}$/ }
28
+ if 1 == dirs.size
29
+ @srcdir = "#{cabinet.srcdir}/#{dirs[0]}"
30
+ else
31
+ @srcdir = Dir.new(cabinet.srcdir).find { |s| s =~ Regexp.new('^' + Regexp.escape(name)) }
32
+ end
33
+ throw :stop, "Unable to determine source directory for package #{name}" if not @srcdir
34
+ puts "Choosing #{@srcdir} as source code folder"
35
+ @srcdir
36
+ end
37
+
38
+ def stage_root
39
+ File.join cabinet.stage_root, long_name
40
+ end
41
+
42
+ package_method :prepare
43
+ package_method :config
44
+ package_method :build
45
+ package_method :stage
46
+ package_method :make
47
+
48
+ def default_prepare
49
+ puts "DEBUG PackageActions#default_prepare"
50
+ files.each do |f|
51
+ unpack = case f
52
+ when /gz$/; '-z'
53
+ when /bz2$/; '-j'
54
+ else ''
55
+ end
56
+ if not Purple.sys "tar x #{unpack} -C '#{cabinet.srcdir}' -f #{cabinet.filesdir}/#{f}"
57
+ throw :stop
58
+ end
59
+ end
60
+
61
+ end
62
+
63
+ def default_config
64
+ throw :stop unless system "cd #{srcdir}; ./configure --prefix=/usr"
65
+ end
66
+
67
+ def default_build
68
+ throw :stop unless system "make -C '#{srcdir}'"
69
+ end
70
+
71
+ def default_stage
72
+ system "rm -fr '#{stage_root}/*'"
73
+
74
+ require 'purple/makefile'
75
+
76
+ puts "DEBUG PackageActions#default_stage: srcdir=#{srcdir}"
77
+ mkm = MakefileMaven.new srcdir
78
+ if mkm.uses_prefix?
79
+ if mkm.uses_destdir?
80
+ make_args = "DESTDIR='#{stage_root}'"
81
+ else
82
+ make_args = "prefix='#{stage_root}/usr'"
83
+ end
84
+ else
85
+ if mkm.uses_destdir?
86
+ make_args = "DESTDIR='#{stage_root}'"
87
+ else
88
+ raise 'Unable to find a way to stage! Package neither defines prefix or DESTDIR'
89
+ end
90
+ end
91
+
92
+ throw :stop if not system "make -C '#{srcdir}' #{make_args} install"
93
+ end
94
+ end
95
+ end
@@ -0,0 +1,15 @@
1
+
2
+ module Purple
3
+ module Platform
4
+ def self.detect
5
+ case true
6
+ when FileTest.exist?('/etc/debian_version')
7
+ system_brand = :debian
8
+ when (FileTest.directory?('/System/Library/') and FileTest.file?('/mach_kernel'))
9
+ system_brand = :osx
10
+ end
11
+
12
+ require "purple/#{system_brand}"
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,172 @@
1
+ require 'singleton'
2
+ require 'uri'
3
+ require 'purple'
4
+
5
+
6
+ PURPLE_SCRIPT_TEMPLATE = proc do |cabinet| <<EOS
7
+ # Autogenerated Purple Packaging script.
8
+ # Cabinet name: '#{cabinet.name}'
9
+
10
+ name #{cabinet.name.inspect}
11
+ long_name #{cabinet.long_name.inspect}
12
+
13
+ #{ cabinet.urls.collect { |k,v| "url #{v.inspect}\n" } }
14
+
15
+ #{
16
+ cabinet.packages.collect { |pkg| PURPLE_PACKAGE_TEMPLATE.call pkg }
17
+ }
18
+ EOS
19
+ end
20
+
21
+ PURPLE_PACKAGE_TEMPLATE = proc do |pkg| <<EOS
22
+ package(#{pkg.name.inspect}) { |p|
23
+ #{pkg.files.collect{ |s| " p.file #{s.inspect}" }.join("\n") }
24
+ p.long_name #{pkg.long_name.inspect}
25
+ p.identifier #{pkg.identifier.inspect}
26
+ p.version #{pkg.version.inspect}
27
+ p.major #{pkg.major}
28
+ p.minor #{pkg.minor}
29
+
30
+ # Uncomment and modify for special configuration
31
+ #p.config proc { |pkg|
32
+ # throw :stop unless system "cd \#{pkg.srcdir}; ./configure --prefix=/usr"
33
+ #}
34
+
35
+ }
36
+ EOS
37
+ end
38
+
39
+ module Purple
40
+ class Script
41
+ def self.open filename
42
+ parse File.open(filename).read
43
+ end
44
+
45
+ def self.parse string
46
+ script = self.new
47
+ script.instance_eval string
48
+ puts "DEBUG Purple::Script##parse: cabinet=#{script.cabinet}"
49
+ script.cabinet
50
+ end
51
+
52
+ def initialize
53
+ @cabinet = PurpleCabinet.new
54
+ @package_scripts = Array.new
55
+ end
56
+ attr_reader :cabinet
57
+
58
+ def name name
59
+ @cabinet.name = name
60
+ end
61
+
62
+ def long_name name
63
+ @cabinet.long_name = name
64
+ end
65
+
66
+ def url url
67
+ @cabinet.add_url url
68
+ end
69
+
70
+ def package name=nil
71
+ puts "> #package(#{name.inspect})"
72
+ package = PackageScript.new @cabinet
73
+ @package_scripts << package
74
+ package.name name
75
+ yield package if block_given?
76
+ end
77
+
78
+ def infer
79
+ if not @cabinet.long_name
80
+ @cabinet.long_name = @cabinet.packages[0].long_name
81
+ end
82
+ if not @cabinet.name
83
+ @cabinet.name = @cabinet.packages[0].name
84
+ end
85
+ end
86
+
87
+ def infer_all
88
+ @package_scripts.each { |pkg|
89
+ puts "DEBUG PurpleScript#infer_all"
90
+ pkg.infer
91
+ }
92
+ puts "DEBUG PurpleScript#infer_all: b4end"
93
+ infer
94
+ end
95
+
96
+ def self.write cabinet, filename
97
+ File.open filename, 'w' do |f|
98
+ f.write dump(cabinet)
99
+ end
100
+ end
101
+ def self.dump cabinet
102
+ PURPLE_SCRIPT_TEMPLATE.call cabinet
103
+ end
104
+
105
+ class PackageScript
106
+ def self.callthrough (*ss)
107
+ ss.each do |s|
108
+ module_eval <<-EOS
109
+ def #{s} value
110
+ @package.#{s} = value
111
+ end
112
+ EOS
113
+ end
114
+ end
115
+
116
+ def initialize cabinet
117
+ @package = cabinet.create_package
118
+ @cabinet = cabinet
119
+ puts "DEBUG PackageScript#initialize: @package=#{@package}"
120
+ end
121
+
122
+ callthrough :long_name, :name, :identifier, :version, :major, :minor
123
+ callthrough :prepare, :config, :build, :stage, :make
124
+
125
+ def pkg
126
+ @package
127
+ end
128
+
129
+ def file filename
130
+ pkg.files << filename
131
+ end
132
+
133
+ def infer
134
+ puts "DEBUG #infer"
135
+ puts "DEBUG PackageScript#infer: pkg=#{pkg}"
136
+ # Take a guess at the filename
137
+ if 0 == pkg.files.size
138
+ files = @cabinet.files
139
+ puts "DEBUG #infer: cabinet_files=#{files.inspect}"
140
+ if 0 == files.size
141
+ warn 'Cabinet files section is empty. Did you not specify any urls?'
142
+ else
143
+ if pkg.long_name
144
+ # See if any filenames match the long name
145
+ rs = files.grep Regexp.new(Regexp.escape(pkg.long_name))
146
+ file rs[0] if 1 == rs.size
147
+ else
148
+ # Else just guess that the first file is the right one
149
+ file files[0]
150
+ end
151
+ end
152
+ end
153
+
154
+ #puts "DEBUG #infer: pkg.files=#{pkg.files.inspect}"
155
+ #puts "DEBUG #infer: long_name=#{pkg.long_name}"
156
+ # Take a guess at properties long_name, name, version, major, and minor
157
+ md = Matches.match_filename pkg.files[0]
158
+ puts "DEBUG #infer: filename match result #{md.inspect}"
159
+
160
+ pkg.long_name = "#{md[:name]}-#{md[:version]}" if not pkg.long_name
161
+ pkg.name = md[:name] if not pkg.name
162
+ pkg.version = md[:version] if not pkg.version
163
+
164
+ md = /^([0-9]+)\.([0-9]+).*/.match pkg.version
165
+ pkg.major = md[1] if md and not pkg.major
166
+ pkg.minor = md[2] if md and not pkg.minor
167
+
168
+ end
169
+ end
170
+
171
+ end
172
+ end
data/lib/purple.rb ADDED
@@ -0,0 +1,221 @@
1
+ require 'singleton'
2
+ require 'fileutils'
3
+
4
+ module Purple
5
+ autoload :PackageActions, 'purple/pkg_actions'
6
+ autoload :Getter, 'purple/getter'
7
+ autoload :Script, 'purple/script'
8
+ autoload :Matches, 'purple/matches'
9
+ autoload :Platform, 'purple/platform'
10
+ PURPLE_FOLDER = "#{ENV['HOME']}/purple"
11
+
12
+
13
+ class PurpleCabinet
14
+ def initialize
15
+ @packages = Array.new
16
+ @urls = Hash.new
17
+ @files = Array.new
18
+ end
19
+ attr_accessor :name, :long_name
20
+ attr_reader :urls, :files, :packages, :cabinet_dir
21
+
22
+ # -> aString # Get source dir
23
+ def filesdir
24
+ assert_dir File.join(@cabinet_dir, 'Files')
25
+ end
26
+
27
+ def srcdir
28
+ assert_dir File.join(@cabinet_dir, 'Source')
29
+ end
30
+
31
+ def stage_root
32
+ assert_dir File.join(@cabinet_dir, 'StageRoot')
33
+ end
34
+
35
+ def packagedir
36
+ assert_dir File.join(@cabinet_dir, 'Package')
37
+ end
38
+
39
+ def fetch_all
40
+ urls.each do |url|
41
+ Getter.get url, filesdir
42
+ end
43
+ end
44
+
45
+ def add_url url
46
+ filename = File.basename URI.parse(url).path
47
+ @urls[filename] = url
48
+ @files << filename
49
+ end
50
+
51
+ def setup
52
+ raise 'cabinet long_name not properly set' if not long_name
53
+ @cabinet_dir = File.join(PURPLE_FOLDER, long_name)
54
+ assert_dir @cabinet_dir
55
+ end
56
+
57
+ def fetch filename
58
+ if not FileTest.exist? "#{filesdir}/#{filename}"
59
+ g = Getter.new urls[filename], filesdir
60
+ g.get
61
+ status = 'Getting'
62
+ loop do
63
+ status, done = *(g.get_status)
64
+ printf "\015\033[MFetching %-40s %3d%% %s", filename, done, status
65
+ $defout.flush
66
+ sleep 1
67
+ break if 'Getting' != status
68
+ end
69
+ puts
70
+ throw :stop, "There was an error while fetching file #{filename}" unless 'Done' == status
71
+ end
72
+ end
73
+
74
+ def prepare
75
+ @packages.each do |p|
76
+ p.files.each { |f| fetch f }
77
+ p.prepare
78
+ end
79
+ end
80
+
81
+ def config
82
+ @packages.each { |p|
83
+ return false if not p.config
84
+ }
85
+ end
86
+
87
+ def build
88
+ @packages.each { |p|
89
+ return false if not p.build
90
+ }
91
+ end
92
+
93
+ def stage
94
+ @packages.each { |p|
95
+ return false if not p.stage
96
+ }
97
+ end
98
+
99
+ def deps
100
+ true
101
+ end
102
+
103
+ def run_steps steps=[:prepare, :build, :deps, :make]
104
+ steps.each do |step|
105
+ self.method(step).call
106
+ end
107
+ end
108
+
109
+ ## ##
110
+
111
+ def create_package
112
+ p = PackageInfo.new
113
+ class <<p
114
+ include PackageActions
115
+ end
116
+ p.cabinet = self
117
+ @packages << p
118
+ @packages.last
119
+ end
120
+
121
+ ## ##
122
+
123
+ def assert_dir path
124
+ unless FileTest.exist? path
125
+ puts ">- Creating folder #{path}"
126
+ Dir.mkdir path
127
+ end
128
+ (FileTest.directory? path) ? path : nil
129
+ end
130
+
131
+ end
132
+
133
+ class PackageInfo
134
+ def initialize
135
+ @files = []
136
+ end
137
+ attr_accessor :long_name, :name, :version, :major, :minor, :identifier, :description
138
+ attr_reader :files
139
+ end
140
+
141
+ class PurpleFile
142
+ def self.parse str
143
+ pkg = PackageInfo.new
144
+ receiver_stack = ['main']
145
+ str.split(/(\r\n|\r|\n)+/).each do |line|
146
+ r = self.method("__#{receiver_stack.last}").call line.strip, pkg
147
+ case r
148
+ when -1
149
+ receiver_stack.pop
150
+ when nil
151
+ else
152
+ receiver_stack.push r
153
+ end
154
+ end
155
+ pkg
156
+ end
157
+
158
+ def self.__main line, pkg
159
+ case line
160
+ when /^package/
161
+ pkg.name = line.gsub(/^package\s+/, '')
162
+ return 'package'
163
+ end
164
+ end
165
+
166
+ PROPS = 'longname|version|major|minor|identifier|description|url'
167
+ def self.__package line, pkg
168
+ if (md = Regexp.new("^(#{PROPS})\s+(.*)$").match line)
169
+ pkg.method("#{md[1]}=").call md[2]
170
+ else
171
+ self.infer_properties pkg if line == 'infer'
172
+ end
173
+ nil
174
+ end
175
+
176
+ def self.infer_properties pkg
177
+ if pkg.url
178
+ if pkg.url =~ /prdownloads.sourceforge.net/
179
+ md = Regexp.new 'http://prdownloads.sourceforge.net/([^/])/(.*?)tar.(gz|bz2)?download'
180
+ pkg.long_name = md[2]
181
+ end
182
+ end
183
+
184
+ pkg.long_name = File.basename Dir.pwd if not pkg.long_name
185
+
186
+ md = /([a-z\-]+)-([0-9\-\.]+.*)/.match pkg.long_name
187
+ pkg.version = md[2] if not pkg.version
188
+
189
+ md = /^([0-9]+)\.([0-9]+)/.match pkg.version
190
+ pkg.major = md[1] if not pkg.major
191
+ pkg.minor = md[2] if not pkg.minor
192
+
193
+ end
194
+ end
195
+
196
+ def self.cabinet_from_url url
197
+
198
+ cabinet = Purple::Script.parse(<<-EOS
199
+ url #{url.inspect}
200
+ package # {|pkg| pkg.infer }
201
+ infer_all
202
+ EOS
203
+ )
204
+ cabinet.setup
205
+ Purple::Script.write cabinet, File.join(cabinet.cabinet_dir, cabinet.name + '.purple')
206
+ cabinet
207
+ end
208
+
209
+ def self.sys cmd
210
+ system cmd
211
+ end
212
+
213
+ end
214
+
215
+ module Kernel
216
+ alias_method :_system_, :system
217
+ def system(*args)
218
+ puts "> #{args.join " "}"
219
+ _system_(*args)
220
+ end
221
+ end
metadata ADDED
@@ -0,0 +1,49 @@
1
+ --- !ruby/object:Gem::Specification
2
+ rubygems_version: 0.8.1
3
+ specification_version: 1
4
+ name: purplepkg
5
+ version: !ruby/object:Gem::Version
6
+ version: 0.0.3
7
+ date: 2004-11-12
8
+ summary: A simple pre-packing tool with meta-package plugin support.
9
+ require_paths:
10
+ - lib
11
+ author: Simon Conrad-Armes
12
+ email: curne@curnomatic.dk
13
+ homepage: purplepkg.rubyforge.org
14
+ rubyforge_project: purple
15
+ description:
16
+ autorequire:
17
+ default_executable:
18
+ bindir: bin
19
+ has_rdoc: false
20
+ required_ruby_version: !ruby/object:Gem::Version::Requirement
21
+ requirements:
22
+ -
23
+ - ">"
24
+ - !ruby/object:Gem::Version
25
+ version: 0.0.0
26
+ version:
27
+ platform: ruby
28
+ files:
29
+ - lib/purple
30
+ - lib/purple.rb
31
+ - lib/purple/matches.rb
32
+ - lib/purple/getter_cp.rb
33
+ - lib/purple/getter_wget.rb
34
+ - lib/purple/osx.rb
35
+ - lib/purple/pkg_actions.rb
36
+ - lib/purple/script.rb
37
+ - lib/purple/makefile.rb
38
+ - lib/purple/getter.rb
39
+ - lib/purple/platform.rb
40
+ - bin/purple
41
+ - bin/install_ruby
42
+ test_files: []
43
+ rdoc_options: []
44
+ extra_rdoc_files: []
45
+ executables:
46
+ - purple
47
+ extensions: []
48
+ requirements: []
49
+ dependencies: []