lapack 0.0.1
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.
- checksums.yaml +7 -0
- data/bin/lapack +158 -0
- data/lib/laenv.rb +67 -0
- data/lib/lapack.rb +158 -0
- data/lib/providers/ctan.rb +141 -0
- data/lib/providers/github.rb +154 -0
- data/lib/providers/provider.rb +73 -0
- metadata +50 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: a32f288093b94bf12f8789649f2e8884c754eb2c
|
4
|
+
data.tar.gz: 79d5b3922a9cc648ea1c4a61a3c4c7ac55ca4cec
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: da3986890cd9a6b3bec1631689bde398cef3f741656d9898f1c569518103b20cb0b7249978bd0d1a740aad9674ede2a1ed285200dce3616fa2fdd86484fe72be
|
7
|
+
data.tar.gz: 00f898dcdf6444c35f2fea7d4cf2435749e628d57c9da88b4335cb4361aa7306c83fcc2d2e94bf9d01c282ce5ca078e30d52b0ae2702bede7d8cb7da8c235998
|
data/bin/lapack
ADDED
@@ -0,0 +1,158 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
# Provides download uri functionality
|
4
|
+
require 'open-uri'
|
5
|
+
# Utils for linking, copying, removing files
|
6
|
+
require 'fileutils'
|
7
|
+
|
8
|
+
# Color output to console
|
9
|
+
# TODO: If not installed replace with fake mixin.
|
10
|
+
require 'colorize'
|
11
|
+
|
12
|
+
# JSON parsing and generation
|
13
|
+
require 'json'
|
14
|
+
|
15
|
+
# Provides methods for working with temp dirs
|
16
|
+
require 'tmpdir'
|
17
|
+
|
18
|
+
ENV['LAPACK'] = File.dirname(File.realpath(__FILE__))
|
19
|
+
|
20
|
+
DEBUG = true
|
21
|
+
|
22
|
+
require "laenv"
|
23
|
+
require "providers/provider"
|
24
|
+
require "providers/ctan"
|
25
|
+
require "providers/github"
|
26
|
+
|
27
|
+
|
28
|
+
module LaPack
|
29
|
+
# Init dbs structure
|
30
|
+
LENV.dbs_init
|
31
|
+
# TODO: Move in latools or lacore
|
32
|
+
LOG_LEVELS = {
|
33
|
+
warning: "*\t%s".light_red,
|
34
|
+
info: "*\t".yellow.bold + "%s".blue.bold,
|
35
|
+
succes: "*\t".green.bold + "%s".green,
|
36
|
+
error: "*\t".red.bold + "%s".red.bold,
|
37
|
+
plain: "%s"
|
38
|
+
}
|
39
|
+
|
40
|
+
### Получаем файл по url и складываем его по имени файла
|
41
|
+
## url - вообще говоря uri
|
42
|
+
## dst - путь к файлу, в который записываем
|
43
|
+
## laenv - окружение, в котором работаем
|
44
|
+
def LaPack.get(url, dst)
|
45
|
+
log("Fetching #{url.white.bold} to #{dst.white.bold}")
|
46
|
+
File.open(dst, "w"){|f| f << LaPack.gets(url)}
|
47
|
+
end
|
48
|
+
|
49
|
+
def LaPack.gets(url)
|
50
|
+
open(url).read
|
51
|
+
end
|
52
|
+
|
53
|
+
##
|
54
|
+
# List available packages for +dbs+
|
55
|
+
#
|
56
|
+
def LaPack.list(*dbs)
|
57
|
+
if dbs.length == 1 && dbs.first.eql?("all")
|
58
|
+
# TODO:
|
59
|
+
log("`all` unsupported yet", :warning)
|
60
|
+
else
|
61
|
+
# TODO: More sofisticated pretty pring
|
62
|
+
# TODO: assuming we had json like structure
|
63
|
+
dbs.each do |dbname|
|
64
|
+
LENV.db(dbname).list.each do |entry|
|
65
|
+
printf("%#{-60}s %s\n", "#{dbname.magenta}/#{entry[:name].magenta.bold}", "#{entry[:caption].blue.bold}")
|
66
|
+
end
|
67
|
+
puts
|
68
|
+
puts
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
##
|
74
|
+
# Add db by name if supported
|
75
|
+
#
|
76
|
+
def LaPack.add_db(name, args = {})
|
77
|
+
LENV.add(name.to_s, args) unless !LENV.supports?(name)
|
78
|
+
end
|
79
|
+
|
80
|
+
##
|
81
|
+
# Logging method
|
82
|
+
# TODO: Remove from LaPack module. Move to utils.rb
|
83
|
+
def LaPack.log(string, level = :info)
|
84
|
+
puts LOG_LEVELS[level] % string unless LENV.quiet? # Do not print anything if quiet
|
85
|
+
end
|
86
|
+
|
87
|
+
##
|
88
|
+
# Add db to local repo. Creates needed structure @ ~/.config/lapack/db
|
89
|
+
#
|
90
|
+
def LaPack.add(db, args={})
|
91
|
+
add_db(db, args={})
|
92
|
+
end
|
93
|
+
|
94
|
+
##
|
95
|
+
# Install packages.
|
96
|
+
# If last argument from packages list is directory
|
97
|
+
# install all packages to directory
|
98
|
+
# else
|
99
|
+
# install to current working dir
|
100
|
+
#
|
101
|
+
def LaPack.install(db, *packages)
|
102
|
+
raise "Empty package list" unless !packages.last.nil? # No packages specified at all
|
103
|
+
|
104
|
+
if File.directory?(packages.last)
|
105
|
+
to_dir = packages.last
|
106
|
+
packages = packages[0..(packages.length - 2)]
|
107
|
+
|
108
|
+
LENV.db(db).install(to_dir, *packages)
|
109
|
+
else
|
110
|
+
LENV.db(db).install('.', *packages)
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
##
|
115
|
+
# Fetch package index for +dbnames+
|
116
|
+
#
|
117
|
+
def LaPack.update(*dbnames)
|
118
|
+
dbnames.each do |dbname|
|
119
|
+
LENV.db(dbname).update
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
##
|
124
|
+
# Show installed dbs
|
125
|
+
#
|
126
|
+
def LaPack.dbs
|
127
|
+
log("Currently plugged dbs:")
|
128
|
+
log(LENV.dbs.map{|d| "\t* %s".white.bold % d}.join("\n"), :plain)
|
129
|
+
end
|
130
|
+
|
131
|
+
##
|
132
|
+
# Show package info for +package+ from +db+
|
133
|
+
def LaPack.show(db, package)
|
134
|
+
puts JSON.pretty_generate(LENV.db(db).show(package))
|
135
|
+
end
|
136
|
+
|
137
|
+
|
138
|
+
##
|
139
|
+
# Remove packages from store
|
140
|
+
def LaPack.remove(db, *packages)
|
141
|
+
raise "Empty package list" unless !packages.last.nil? # No packages specified at all
|
142
|
+
|
143
|
+
LENV.db(db).remove(*packages)
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
if (ARGV.empty?)
|
148
|
+
puts "No args passed"
|
149
|
+
else
|
150
|
+
begin
|
151
|
+
LaPack.send(ARGV[0], *ARGV[1..ARGV.length])
|
152
|
+
rescue NoMethodError => undefined
|
153
|
+
puts "Unknown operation #{undefined.name}"
|
154
|
+
rescue Exception => e
|
155
|
+
puts e
|
156
|
+
puts $!.backtrace if DEBUG
|
157
|
+
end
|
158
|
+
end
|
data/lib/laenv.rb
ADDED
@@ -0,0 +1,67 @@
|
|
1
|
+
module LaPack
|
2
|
+
##
|
3
|
+
# Enviroment class for lapack.
|
4
|
+
# Defines runtime options
|
5
|
+
#
|
6
|
+
class LaEnv
|
7
|
+
|
8
|
+
attr_reader(:lastore, :ladb, :lapkg)
|
9
|
+
|
10
|
+
def initialize(args={})
|
11
|
+
@quiet = args.delete(:quiet) || false
|
12
|
+
@lastore = File.expand_path(args.delete(:lastore)|| "~/.config/lapack")
|
13
|
+
@ladb = "db"
|
14
|
+
@lapkg = "pkg"
|
15
|
+
FileUtils.mkdir_p(dbs_store)
|
16
|
+
|
17
|
+
raise "Unknown args #{args.keys.join(', ')}" unless args.keys.empty?
|
18
|
+
end
|
19
|
+
|
20
|
+
def quiet?
|
21
|
+
@quiet
|
22
|
+
end
|
23
|
+
|
24
|
+
##
|
25
|
+
# Returns dbs path
|
26
|
+
#
|
27
|
+
def dbs_store
|
28
|
+
File.join(@lastore, ladb)
|
29
|
+
end
|
30
|
+
|
31
|
+
def db(name)
|
32
|
+
@dbs_hash[name.to_sym]
|
33
|
+
end
|
34
|
+
|
35
|
+
def dbs
|
36
|
+
@dbs_hash.keys
|
37
|
+
end
|
38
|
+
|
39
|
+
def add(db, params = {})
|
40
|
+
if(db.to_sym.eql?(:ctan))
|
41
|
+
File.open(File.join(dbs_store, "#{db}.db"), "w") {|f| f << {name: 'ctan', clazz: 'CtanProvider', params: {}}.to_json}
|
42
|
+
elsif (db.to_sym.eql?(:github))
|
43
|
+
File.open(File.join(dbs_store, "#{db}.db"), "w") {|f| f << {name: 'github', clazz: 'GithubProvider', params: {}}.to_json}
|
44
|
+
else
|
45
|
+
raise "Unsupported"
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def supports?(dbtype)
|
50
|
+
(:ctan.eql? dbtype.to_sym) || (:github.eql? dbtype.to_sym)
|
51
|
+
end
|
52
|
+
|
53
|
+
def dbs_init
|
54
|
+
@dbs_hash = Dir["#{dbs_store}/*.db"]
|
55
|
+
.map do |dbfile|
|
56
|
+
File.open(dbfile){|f| JSON.parse(f.read, symbolize_names: true)}
|
57
|
+
end
|
58
|
+
.inject({}) do |h, db|
|
59
|
+
h.update({
|
60
|
+
db[:name].to_sym => LaPack::const_get(db[:clazz]).new(self, db[:params])
|
61
|
+
})
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
LENV = LaEnv.new
|
67
|
+
end
|
data/lib/lapack.rb
ADDED
@@ -0,0 +1,158 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
# Provides download uri functionality
|
4
|
+
require 'open-uri'
|
5
|
+
# Utils for linking, copying, removing files
|
6
|
+
require 'fileutils'
|
7
|
+
|
8
|
+
# Color output to console
|
9
|
+
# TODO: If not installed replace with fake mixin.
|
10
|
+
require 'colorize'
|
11
|
+
|
12
|
+
# JSON parsing and generation
|
13
|
+
require 'json'
|
14
|
+
|
15
|
+
# Provides methods for working with temp dirs
|
16
|
+
require 'tmpdir'
|
17
|
+
|
18
|
+
ENV['LAPACK'] = File.dirname(File.realpath(__FILE__))
|
19
|
+
|
20
|
+
DEBUG = true
|
21
|
+
|
22
|
+
require "laenv"
|
23
|
+
require "providers/provider"
|
24
|
+
require "providers/ctan"
|
25
|
+
require "providers/github"
|
26
|
+
|
27
|
+
|
28
|
+
module LaPack
|
29
|
+
# Init dbs structure
|
30
|
+
LENV.dbs_init
|
31
|
+
# TODO: Move in latools or lacore
|
32
|
+
LOG_LEVELS = {
|
33
|
+
warning: "*\t%s".light_red,
|
34
|
+
info: "*\t".yellow.bold + "%s".blue.bold,
|
35
|
+
succes: "*\t".green.bold + "%s".green,
|
36
|
+
error: "*\t".red.bold + "%s".red.bold,
|
37
|
+
plain: "%s"
|
38
|
+
}
|
39
|
+
|
40
|
+
### Получаем файл по url и складываем его по имени файла
|
41
|
+
## url - вообще говоря uri
|
42
|
+
## dst - путь к файлу, в который записываем
|
43
|
+
## laenv - окружение, в котором работаем
|
44
|
+
def LaPack.get(url, dst)
|
45
|
+
log("Fetching #{url.white.bold} to #{dst.white.bold}")
|
46
|
+
File.open(dst, "w"){|f| f << LaPack.gets(url)}
|
47
|
+
end
|
48
|
+
|
49
|
+
def LaPack.gets(url)
|
50
|
+
open(url).read
|
51
|
+
end
|
52
|
+
|
53
|
+
##
|
54
|
+
# List available packages for +dbs+
|
55
|
+
#
|
56
|
+
def LaPack.list(*dbs)
|
57
|
+
if dbs.length == 1 && dbs.first.eql?("all")
|
58
|
+
# TODO:
|
59
|
+
log("`all` unsupported yet", :warning)
|
60
|
+
else
|
61
|
+
# TODO: More sofisticated pretty pring
|
62
|
+
# TODO: assuming we had json like structure
|
63
|
+
dbs.each do |dbname|
|
64
|
+
LENV.db(dbname).list.each do |entry|
|
65
|
+
printf("%#{-60}s %s\n", "#{dbname.magenta}/#{entry[:name].magenta.bold}", "#{entry[:caption].blue.bold}")
|
66
|
+
end
|
67
|
+
puts
|
68
|
+
puts
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
##
|
74
|
+
# Add db by name if supported
|
75
|
+
#
|
76
|
+
def LaPack.add_db(name, args = {})
|
77
|
+
LENV.add(name.to_s, args) unless !LENV.supports?(name)
|
78
|
+
end
|
79
|
+
|
80
|
+
##
|
81
|
+
# Logging method
|
82
|
+
# TODO: Remove from LaPack module. Move to utils.rb
|
83
|
+
def LaPack.log(string, level = :info)
|
84
|
+
puts LOG_LEVELS[level] % string unless LENV.quiet? # Do not print anything if quiet
|
85
|
+
end
|
86
|
+
|
87
|
+
##
|
88
|
+
# Add db to local repo. Creates needed structure @ ~/.config/lapack/db
|
89
|
+
#
|
90
|
+
def LaPack.add(db, args={})
|
91
|
+
add_db(db, args={})
|
92
|
+
end
|
93
|
+
|
94
|
+
##
|
95
|
+
# Install packages.
|
96
|
+
# If last argument from packages list is directory
|
97
|
+
# install all packages to directory
|
98
|
+
# else
|
99
|
+
# install to current working dir
|
100
|
+
#
|
101
|
+
def LaPack.install(db, *packages)
|
102
|
+
raise "Empty package list" unless !packages.last.nil? # No packages specified at all
|
103
|
+
|
104
|
+
if File.directory?(packages.last)
|
105
|
+
to_dir = packages.last
|
106
|
+
packages = packages[0..(packages.length - 2)]
|
107
|
+
|
108
|
+
LENV.db(db).install(to_dir, *packages)
|
109
|
+
else
|
110
|
+
LENV.db(db).install('.', *packages)
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
##
|
115
|
+
# Fetch package index for +dbnames+
|
116
|
+
#
|
117
|
+
def LaPack.update(*dbnames)
|
118
|
+
dbnames.each do |dbname|
|
119
|
+
LENV.db(dbname).update
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
##
|
124
|
+
# Show installed dbs
|
125
|
+
#
|
126
|
+
def LaPack.dbs
|
127
|
+
log("Currently plugged dbs:")
|
128
|
+
log(LENV.dbs.map{|d| "\t* %s".white.bold % d}.join("\n"), :plain)
|
129
|
+
end
|
130
|
+
|
131
|
+
##
|
132
|
+
# Show package info for +package+ from +db+
|
133
|
+
def LaPack.show(db, package)
|
134
|
+
puts JSON.pretty_generate(LENV.db(db).show(package))
|
135
|
+
end
|
136
|
+
|
137
|
+
|
138
|
+
##
|
139
|
+
# Remove packages from store
|
140
|
+
def LaPack.remove(db, *packages)
|
141
|
+
raise "Empty package list" unless !packages.last.nil? # No packages specified at all
|
142
|
+
|
143
|
+
LENV.db(db).remove(*packages)
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
if (ARGV.empty?)
|
148
|
+
puts "No args passed"
|
149
|
+
else
|
150
|
+
begin
|
151
|
+
LaPack.send(ARGV[0], *ARGV[1..ARGV.length])
|
152
|
+
rescue NoMethodError => undefined
|
153
|
+
puts "Unknown operation #{undefined.name}"
|
154
|
+
rescue Exception => e
|
155
|
+
puts e
|
156
|
+
puts $!.backtrace if DEBUG
|
157
|
+
end
|
158
|
+
end
|
@@ -0,0 +1,141 @@
|
|
1
|
+
module LaPack
|
2
|
+
|
3
|
+
class CtanProvider < Provider
|
4
|
+
|
5
|
+
def initialize(env, params = {})
|
6
|
+
super env, 'ctan', params
|
7
|
+
|
8
|
+
## Here is where package index stored
|
9
|
+
@package_list = 'http://ctan.org/json/packages'
|
10
|
+
## Here you can find info about package
|
11
|
+
@package_info = 'http://ctan.org/json/pkg/%s'
|
12
|
+
end
|
13
|
+
|
14
|
+
def init(dbdir)
|
15
|
+
# dbdir path
|
16
|
+
@dbdir = dbdir
|
17
|
+
# dbdir name
|
18
|
+
@packages = File.join(dbdir, 'pkg')
|
19
|
+
# Package index
|
20
|
+
@index = File.join(dbdir, "#{@name}.json")
|
21
|
+
# Ctan archive fetch
|
22
|
+
@ctan_fetch = 'http://mirrors.ctan.org%s'
|
23
|
+
|
24
|
+
FileUtils.mkdir_p(@packages) unless File.exists?(@packages)
|
25
|
+
|
26
|
+
raise "Can't write to #{@packages}. Not a directory" unless File.directory?(@packages)
|
27
|
+
end
|
28
|
+
|
29
|
+
def update
|
30
|
+
LaPack.get(@package_list, @index)
|
31
|
+
end
|
32
|
+
|
33
|
+
def list
|
34
|
+
raise "Update db first" unless File.exists?(@index)
|
35
|
+
File.open(@index, "r") {|f| JSON.parse(f.read, symbolize_names: true)}
|
36
|
+
end
|
37
|
+
|
38
|
+
def show(package)
|
39
|
+
JSON.parse(LaPack.gets(@package_info % package), symbolize_names: true)
|
40
|
+
end
|
41
|
+
|
42
|
+
def install(to_dir, *packages)
|
43
|
+
packages.each do |package|
|
44
|
+
LaPack.log("Installing #{package.blue.bold}")
|
45
|
+
if list.select{|p| p[:name].eql?(package)}.empty?
|
46
|
+
raise "No such package #{package.white.bold}"
|
47
|
+
else
|
48
|
+
install_package(package, to_dir)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def remove(*packages)
|
54
|
+
packages.each do |package|
|
55
|
+
LaPack.log("Removing #{package.blue.bold}")
|
56
|
+
if list.select{|p| p[:name].eql?(package)}.empty?
|
57
|
+
raise "No such package #{package.white.bold}"
|
58
|
+
else
|
59
|
+
ctan_remove(package)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
private
|
65
|
+
##
|
66
|
+
# Install package routine
|
67
|
+
#
|
68
|
+
def install_package(package, to_dir)
|
69
|
+
|
70
|
+
package_dir = File.join(@packages, package)
|
71
|
+
FileUtils.mkdir_p(package_dir)
|
72
|
+
package_info = show(package)
|
73
|
+
# If exists #{package}.json - we already have some version of
|
74
|
+
# package. So check version and go ahead.
|
75
|
+
package_info_store = File.join(package_dir, "#{package}.json")
|
76
|
+
current = {}
|
77
|
+
if (File.exists?(package_info_store))
|
78
|
+
current = JSON.parse(File.open(package_info_store){|f| f.read}, symbolize_names: true)
|
79
|
+
end
|
80
|
+
|
81
|
+
# Current does not exists or is out of date
|
82
|
+
# (assuming we always had newer version @ CTAN. Thats little bit wrong)
|
83
|
+
if current.empty? || !current[:version][:number].eql?(package_info[:version][:number])
|
84
|
+
|
85
|
+
LaPack.log("Updating #{package}: #{current[:version][:number]} ~> #{package_info[:version][:number]}") unless current.empty?
|
86
|
+
|
87
|
+
# Create tmp dir and do make routine
|
88
|
+
Dir.mktmpdir("lapack-#{package}-") do |tmp|
|
89
|
+
stys = []
|
90
|
+
# Currently we can make from :ctan field. That is mostly common case
|
91
|
+
if package_info.has_key?(:ctan)
|
92
|
+
stys = ctan_install(package_info, tmp)
|
93
|
+
elsif package_info.has_key?(:install)
|
94
|
+
LaPack.log("Don't know how to build from install")
|
95
|
+
elsif package_info.has_key?(:texlive)
|
96
|
+
LaPack.log("Don't know how to build from texlive")
|
97
|
+
else
|
98
|
+
raise("Don't know how to build #{package}")
|
99
|
+
end
|
100
|
+
|
101
|
+
# stys contains path list for all artifacts
|
102
|
+
# we'll copy them to package dist dir
|
103
|
+
stys.each{|sty| FileUtils.cp(sty, package_dir)}
|
104
|
+
|
105
|
+
# Flush package info to package dist dir
|
106
|
+
File.open(package_info_store, "w"){|f| f << package_info.to_json}
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
# Relinking stys
|
111
|
+
LaPack.log("Linking #{package} content to #{to_dir}")
|
112
|
+
Dir["#{package_dir}/*.sty"].each do |sty|
|
113
|
+
FileUtils.ln_s(sty, to_dir, force: true)
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
def ctan_install(package_info, tmpdir)
|
118
|
+
# Place were package archive stored @ CTAN
|
119
|
+
link = (@ctan_fetch % package_info[:ctan][:path]) + ".zip"
|
120
|
+
|
121
|
+
arch = File.join(tmpdir, "#{package_info[:name]}.zip")
|
122
|
+
# Unpack archive
|
123
|
+
LaPack.get(link, arch)
|
124
|
+
`unzip #{arch} -d #{File.join(tmpdir, "src")}`
|
125
|
+
Dir["#{tmpdir}/**/*.ins"].each do |ins|
|
126
|
+
# And do latex on each *.ins file
|
127
|
+
Dir.chdir(File.dirname(ins)) do |dir|
|
128
|
+
LaPack.log("LaTex on #{ins}")
|
129
|
+
system "latex #{ins}"
|
130
|
+
end
|
131
|
+
end
|
132
|
+
# Return list of *.sty
|
133
|
+
Dir["#{tmpdir}/**/*.sty"]
|
134
|
+
end
|
135
|
+
|
136
|
+
def ctan_remove(package)
|
137
|
+
package_dir = File.join(@packages, package)
|
138
|
+
FileUtils.rm_r(package_dir)
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
@@ -0,0 +1,154 @@
|
|
1
|
+
module LaPack
|
2
|
+
|
3
|
+
class GithubProvider < Provider
|
4
|
+
|
5
|
+
## Entries per github query page
|
6
|
+
@@PER_PAGE = 100
|
7
|
+
|
8
|
+
def initialize(env, params = {})
|
9
|
+
super env, 'github', params
|
10
|
+
|
11
|
+
@github_db = "https://api.github.com/search/repositories?q=language:tex&page=%d&per_page=#{@@PER_PAGE}"
|
12
|
+
end
|
13
|
+
|
14
|
+
def init(dbdir)
|
15
|
+
# dbdir path
|
16
|
+
@dbdir = dbdir
|
17
|
+
# dbdir name
|
18
|
+
@packages = File.join(dbdir, 'pkg')
|
19
|
+
# Package index
|
20
|
+
@index = File.join(dbdir, "#{@name}.json")
|
21
|
+
|
22
|
+
FileUtils.mkdir_p(@packages) unless File.exists?(@packages)
|
23
|
+
|
24
|
+
raise "Can't write to #{@packages}. Not a directory" unless File.directory?(@packages)
|
25
|
+
end
|
26
|
+
|
27
|
+
def update
|
28
|
+
first_page = JSON.parse(LaPack.gets(@github_db % [ 1 ]), symbolize_names: true)
|
29
|
+
repos_count = first_page[:total_count]
|
30
|
+
pages = (repos_count / @@PER_PAGE) + ((repos_count % @@PER_PAGE) == 0 ? 0 : 1)
|
31
|
+
repos = []
|
32
|
+
|
33
|
+
repos << scan_page(first_page)
|
34
|
+
repos << (2..pages).map do |page|
|
35
|
+
sleep(60 / 5) # Five requests per minute limitation
|
36
|
+
LaPack.log("Getting page #{page} from #{pages}")
|
37
|
+
scan_page(JSON.parse(LaPack.gets(@github_db % [page]), symbolize_names: true))
|
38
|
+
end
|
39
|
+
|
40
|
+
File.open(@index, "w") {|f| f << repos.to_json}
|
41
|
+
end
|
42
|
+
|
43
|
+
def scan_page(page)
|
44
|
+
page[:items].map{|item| item.select{|k, v| [:html_url, :name, :description, :git_url, :full_name].include?(k)}}
|
45
|
+
end
|
46
|
+
|
47
|
+
def list
|
48
|
+
LaPack.log("Unavailable", :warning)
|
49
|
+
end
|
50
|
+
|
51
|
+
def show(package)
|
52
|
+
LaPack.log("Unavailable", :warning)
|
53
|
+
end
|
54
|
+
|
55
|
+
def install(to_dir, *packages)
|
56
|
+
packages.each do |package|
|
57
|
+
LaPack.log("Installing #{package.blue.bold}")
|
58
|
+
if list.select{|p| p[:name].eql?(package)}.empty?
|
59
|
+
raise "No such package #{package.white.bold}"
|
60
|
+
else
|
61
|
+
install_package(package, to_dir)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def remove(*packages)
|
67
|
+
packages.each do |package|
|
68
|
+
LaPack.log("Removing #{package.blue.bold}")
|
69
|
+
if list.select{|p| p[:name].eql?(package)}.empty?
|
70
|
+
raise "No such package #{package.white.bold}"
|
71
|
+
else
|
72
|
+
ctan_remove(package)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
private
|
78
|
+
##
|
79
|
+
# Install package routine
|
80
|
+
#
|
81
|
+
def install_package(package, to_dir)
|
82
|
+
|
83
|
+
package_dir = File.join(@packages, package)
|
84
|
+
FileUtils.mkdir_p(package_dir)
|
85
|
+
package_info = show(package)
|
86
|
+
# If exists #{package}.json - we already have some version of
|
87
|
+
# package. So check version and go ahead.
|
88
|
+
package_info_store = File.join(package_dir, "#{package}.json")
|
89
|
+
current = {}
|
90
|
+
if (File.exists?(package_info_store))
|
91
|
+
current = JSON.parse(File.open(package_info_store){|f| f.read}, symbolize_names: true)
|
92
|
+
end
|
93
|
+
|
94
|
+
# Current does not exists or is out of date
|
95
|
+
# (assuming we always had newer version @ CTAN. Thats little bit wrong)
|
96
|
+
if current.empty? || !current[:version][:number].eql?(package_info[:version][:number])
|
97
|
+
|
98
|
+
LaPack.log("Updating #{package}: #{current[:version][:number]} ~> #{package_info[:version][:number]}") unless current.empty?
|
99
|
+
|
100
|
+
# Create tmp dir and do make routine
|
101
|
+
Dir.mktmpdir("lapack-#{package}-") do |tmp|
|
102
|
+
stys = []
|
103
|
+
# Currently we can make from :ctan field. That is mostly common case
|
104
|
+
if package_info.has_key?(:ctan)
|
105
|
+
stys = ctan_install(package_info, tmp)
|
106
|
+
elsif package_info.has_key?(:install)
|
107
|
+
LaPack.log("Don't know how to build from install")
|
108
|
+
elsif package_info.has_key?(:texlive)
|
109
|
+
LaPack.log("Don't know how to build from texlive")
|
110
|
+
else
|
111
|
+
raise("Don't know how to build #{package}")
|
112
|
+
end
|
113
|
+
|
114
|
+
# stys contains path list for all artifacts
|
115
|
+
# we'll copy them to package dist dir
|
116
|
+
stys.each{|sty| FileUtils.cp(sty, package_dir)}
|
117
|
+
|
118
|
+
# Flush package info to package dist dir
|
119
|
+
File.open(package_info_store, "w"){|f| f << package_info.to_json}
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
# Relinking stys
|
124
|
+
LaPack.log("Linking #{package} content to #{to_dir}")
|
125
|
+
Dir["#{package_dir}/*.sty"].each do |sty|
|
126
|
+
FileUtils.ln_s(sty, to_dir, force: true)
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
def ctan_install(package_info, tmpdir)
|
131
|
+
# Place were package archive stored @ CTAN
|
132
|
+
link = (@ctan_fetch % package_info[:ctan][:path]) + ".zip"
|
133
|
+
|
134
|
+
arch = File.join(tmpdir, "#{package_info[:name]}.zip")
|
135
|
+
# Unpack archive
|
136
|
+
LaPack.get(link, arch)
|
137
|
+
`unzip #{arch} -d #{File.join(tmpdir, "src")}`
|
138
|
+
Dir["#{tmpdir}/**/*.ins"].each do |ins|
|
139
|
+
# And do latex on each *.ins file
|
140
|
+
Dir.chdir(File.dirname(ins)) do |dir|
|
141
|
+
LaPack.log("LaTex on #{ins}")
|
142
|
+
system "latex #{ins}"
|
143
|
+
end
|
144
|
+
end
|
145
|
+
# Return list of *.sty
|
146
|
+
Dir["#{tmpdir}/**/*.sty"]
|
147
|
+
end
|
148
|
+
|
149
|
+
def ctan_remove(package)
|
150
|
+
package_dir = File.join(@packages, package)
|
151
|
+
FileUtils.rm_r(package_dir)
|
152
|
+
end
|
153
|
+
end
|
154
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
|
3
|
+
module LaPack
|
4
|
+
##
|
5
|
+
# Base package provider. I.e. database wrapper.
|
6
|
+
#
|
7
|
+
# Should know how to:
|
8
|
+
# * fetch packages index and manage
|
9
|
+
# * show package info
|
10
|
+
# * download, make & install packages
|
11
|
+
# * remove packages
|
12
|
+
# * keeps multiple versions
|
13
|
+
class Provider
|
14
|
+
|
15
|
+
##
|
16
|
+
# Initialization with LaENV instance
|
17
|
+
def initialize(env, name, params)
|
18
|
+
@name = name
|
19
|
+
|
20
|
+
# Check if db dir exists
|
21
|
+
@dbdir = File.join(env.dbs_store, name)
|
22
|
+
if File.exists?(@dbdir)
|
23
|
+
raise "Can't write to #{@dbdir}. Not a directory" unless File.directory?(@dbdir)
|
24
|
+
else
|
25
|
+
FileUtils.mkdir_p(@dbdir)
|
26
|
+
end
|
27
|
+
configure(params)
|
28
|
+
init(@dbdir)
|
29
|
+
end
|
30
|
+
|
31
|
+
##
|
32
|
+
# Configuration
|
33
|
+
#
|
34
|
+
# Accepts any parameters (+params+) for configuration as Hash
|
35
|
+
def configure(params = {})
|
36
|
+
true
|
37
|
+
end
|
38
|
+
|
39
|
+
##
|
40
|
+
# Initialization
|
41
|
+
#
|
42
|
+
# Uses +dbdir+ argument for filesystem initialization
|
43
|
+
# No index update required there.
|
44
|
+
#
|
45
|
+
def init(dbdir)
|
46
|
+
|
47
|
+
end
|
48
|
+
|
49
|
+
##
|
50
|
+
# Updates package index
|
51
|
+
def update
|
52
|
+
true
|
53
|
+
end
|
54
|
+
|
55
|
+
##
|
56
|
+
# Shows available packages
|
57
|
+
def list
|
58
|
+
return []
|
59
|
+
end
|
60
|
+
|
61
|
+
def install(*packages)
|
62
|
+
puts "Dummy implementation. Should install: #{packages.join(",")}"
|
63
|
+
end
|
64
|
+
|
65
|
+
def show(package)
|
66
|
+
[]
|
67
|
+
end
|
68
|
+
|
69
|
+
def remove(package)
|
70
|
+
# do nothing
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
metadata
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: lapack
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Ilya Arkhanhelsky
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-01-04 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description: Simple packaging tool for LaTeX
|
14
|
+
email: ilya.arkhanhelsky@gmail.com
|
15
|
+
executables:
|
16
|
+
- lapack
|
17
|
+
extensions: []
|
18
|
+
extra_rdoc_files: []
|
19
|
+
files:
|
20
|
+
- bin/lapack
|
21
|
+
- lib/laenv.rb
|
22
|
+
- lib/lapack.rb
|
23
|
+
- lib/providers/ctan.rb
|
24
|
+
- lib/providers/github.rb
|
25
|
+
- lib/providers/provider.rb
|
26
|
+
homepage: http://rubygems.org/gems/lapack
|
27
|
+
licenses:
|
28
|
+
- Apache
|
29
|
+
metadata: {}
|
30
|
+
post_install_message:
|
31
|
+
rdoc_options: []
|
32
|
+
require_paths:
|
33
|
+
- lib
|
34
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
35
|
+
requirements:
|
36
|
+
- - ">="
|
37
|
+
- !ruby/object:Gem::Version
|
38
|
+
version: '0'
|
39
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
40
|
+
requirements:
|
41
|
+
- - ">="
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: '0'
|
44
|
+
requirements: []
|
45
|
+
rubyforge_project:
|
46
|
+
rubygems_version: 2.2.2
|
47
|
+
signing_key:
|
48
|
+
specification_version: 4
|
49
|
+
summary: LaPack
|
50
|
+
test_files: []
|