lapack 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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: []
|