gsm-sources-manager 1.0.0.alpha3

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.
Binary file
@@ -0,0 +1,97 @@
1
+ ---
2
+ permalink: index.html
3
+ layout: default
4
+ ---
5
+ <div id="intro">
6
+ <div id="intro-logo">
7
+ <img src="/gsm/image/gsm.png">
8
+ </div>
9
+ <div id="intro-text">
10
+ GSM is a simple sources manager for RubyGems.
11
+ </div>
12
+ <div id="intro-desc">
13
+ In Ruby development, we always need alternative RubyGems source in special networks. e.g. In China Mainland, you know. GSM helps get your gem sources managed.
14
+ </div>
15
+ <div id="intro-button">
16
+ <div class="install-item install-gsm">
17
+ <a href="#install">Install GSM</a>
18
+ </div>
19
+ <div class="install-item install-user-guide">
20
+ <a href="#guide">User Guide</a>
21
+ </div>
22
+ </div>
23
+ <div id="intro-version">
24
+ <span>Version <a href="#changelog">{{ site.data.changelog[0].version }}</a> ·</span>
25
+ <span>Created by <a href="https://crispgm.com">David Zhang</a></span>
26
+ </div>
27
+ </div>
28
+ <div id="social">
29
+ <a class="github-button" href="https://github.com/crispgm/gsm" data-icon="octicon-star" data-count-href="/crispgm/gsm/stargazers" data-count-api="/repos/crispgm/gsm#stargazers_count" data-count-aria-label="# stargazers on GitHub" aria-label="Star crispgm/gsm on GitHub">Star</a>
30
+ <a class="github-button" href="https://github.com/crispgm/gsm/fork" data-icon="octicon-repo-forked" data-count-href="/crispgm/gsm/network" data-count-api="/repos/crispgm/gsm#forks_count" data-count-aria-label="# forks on GitHub" aria-label="Fork crispgm/gsm on GitHub">Fork</a>
31
+ </div>
32
+ <div id="install" class="content">
33
+ <div class="content-title">
34
+ Installation
35
+ </div>
36
+ <div>
37
+ {{ site.data.index.install | markdownify }}
38
+ </div>
39
+ <div class="back-top">
40
+ <a href="#topbar">Back to top</a>
41
+ </div>
42
+ </div>
43
+ <div id="guide" class="content">
44
+ <div class="content-title">
45
+ User Guide
46
+ </div>
47
+ {{ site.data.index.guide | markdownify }}
48
+ <div class="back-top">
49
+ <a href="#topbar">Back to top</a>
50
+ </div>
51
+ </div>
52
+ <div id="changelog" class="content">
53
+ <div class="content-title">
54
+ Changelog
55
+ </div>
56
+ {% for change in site.data.changelog %}
57
+ <h3>Version {{ change.version }}</h3>
58
+ <ul>
59
+ {% for log in change.changes %}
60
+ <li>
61
+ {{ log.text }}
62
+ {% if log.issue != nil %}
63
+ <a href="https://github.com/crispgm/gsm/issues/{{ log.issue }}">#{{ log.issue }}</a></li>
64
+ {% endif %}
65
+ </li>
66
+ {% endfor %}
67
+ </ul>
68
+ {% endfor %}
69
+ <div class="back-top">
70
+ <a href="#topbar">Back to top</a>
71
+ </div>
72
+ </div>
73
+ <div id="contributing" class="content">
74
+ <div class="content-title">
75
+ Contributing
76
+ </div>
77
+ {{ site.data.index.contrib | markdownify }}
78
+ <div class="back-top">
79
+ <a href="#topbar">Back to top</a>
80
+ </div>
81
+ </div>
82
+ <div id="disqus" class="content">
83
+ <div id="disqus_thread"></div>
84
+ <script>
85
+ var disqus_config = function () {
86
+ this.page.url = 'https://crispgm.github.io/gsm/';
87
+ this.page.identifier = 'Home | GSM Sources Manager';
88
+ };
89
+ (function() { // DON'T EDIT BELOW THIS LINE
90
+ var d = document, s = d.createElement('script');
91
+ s.src = '//crispgm-github-io.disqus.com/embed.js';
92
+ s.setAttribute('data-timestamp', +new Date());
93
+ (d.head || d.body).appendChild(s);
94
+ })();
95
+ </script>
96
+ <noscript>Please enable JavaScript to view the <a href="https://disqus.com/?ref_noscript">comments powered by Disqus.</a></noscript>
97
+ </div>
data/exe/gsm ADDED
@@ -0,0 +1,139 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), *%w(.. lib)))
4
+
5
+ require "gsm"
6
+ require "mercenary"
7
+
8
+ Mercenary.program(:gsm) do |p|
9
+ p.version Gsm::VERSION
10
+ p.description "GSM Sources Manager"
11
+ p.syntax "gsm <subcommand> [options]"
12
+
13
+ conf_path = ""
14
+ user_path = Dir.home()
15
+ Dir.chdir(user_path) do
16
+ if !Dir.exist?(".gsm")
17
+ Dir.mkdir(".gsm")
18
+ end
19
+ end
20
+
21
+ conf_path = "#{user_path}/.gsm/sources.yml"
22
+
23
+ gem = Gsm::Gem.new("#{user_path}/sources.yml")
24
+
25
+ p.command(:list) do |c|
26
+ c.syntax "list"
27
+ c.description "List all sources"
28
+
29
+ c.action do |_, _|
30
+ gem.sources.each do |name, url|
31
+ use_mark = ""
32
+ if gem.get == name
33
+ use_mark = "(*)"
34
+ end
35
+ puts "#{name}: #{url} #{use_mark}"
36
+ end
37
+ end
38
+ end
39
+
40
+ p.command(:use) do |c|
41
+ c.syntax "use [source]"
42
+ c.description "Use source"
43
+
44
+ c.action do |args, _|
45
+ name = args[0]
46
+ use = gem.use(name)
47
+ if use
48
+ puts "GSM: Source `#{use}` has been applied."
49
+ else
50
+ puts "GSM Error: Illegal source `#{name}`."
51
+ end
52
+ end
53
+ end
54
+
55
+ p.command(:add) do |c|
56
+ c.syntax "add [name] [url]"
57
+ c.description "Add source"
58
+
59
+ c.option "use", "--use", "Add and use source"
60
+
61
+ c.action do |args, opts|
62
+ name = args[0]
63
+ url = args[1]
64
+ is_use = opts["use"]
65
+
66
+ if gem.add(name, url)
67
+ if is_use
68
+ if !gem.use(name)
69
+ puts "GSM Error: Illegal source `#{name}`."
70
+ end
71
+ end
72
+ else
73
+ puts "GSM Error: Illegal name/url."
74
+ end
75
+ end
76
+ end
77
+
78
+ p.command(:del) do |c|
79
+ c.syntax "del [source]"
80
+ c.description "Delete source"
81
+
82
+ c.action do |args, _|
83
+ name = args[0]
84
+ ret = gem.del(name)
85
+ if ret == false
86
+ puts "GSM Error: Source is in use. Please switch to other source in advance."
87
+ return
88
+ elsif ret == nil
89
+ puts "GSM Error: No source name with `#{name}`."
90
+ return
91
+ end
92
+ end
93
+ end
94
+
95
+ p.command(:reset) do |c|
96
+ c.syntax "reset"
97
+ c.description "Reset all sources"
98
+
99
+ c.action do |_, _|
100
+ gem.reset
101
+ end
102
+ end
103
+
104
+ p.command(:mirror) do |c|
105
+ c.syntax "mirror [source]"
106
+ c.description "Mirror source for Bundler"
107
+
108
+ c.option "reset", "--reset", "Reset bundler mirror"
109
+
110
+ c.action do |args, opts|
111
+ if opts["reset"]
112
+ Gsm::Bundle.reset
113
+ return
114
+ end
115
+
116
+ if args.size == 0
117
+ name = gem.get
118
+ if name.empty?
119
+ puts "GSM Error: no default source for mirror."
120
+ return
121
+ end
122
+ else
123
+ name = args[0]
124
+ end
125
+ Gsm::Bundle.mirror(gem.sources[name])
126
+ end
127
+ end
128
+
129
+ p.command(:help) do |c|
130
+ c.syntax "help"
131
+ c.description "Show usage"
132
+
133
+ c.action do |_, _|
134
+ puts p
135
+ end
136
+ end
137
+
138
+ p.default_command(:help)
139
+ end
@@ -0,0 +1,29 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'gsm/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "gsm-sources-manager"
8
+ spec.version = Gsm::VERSION
9
+ spec.authors = ["David Zhang"]
10
+ spec.email = ["crispgm@gmail.com"]
11
+ spec.summary = "GSM Sources Manager"
12
+ spec.description = "GSM is a simple sources manager for RubyGems."
13
+ spec.homepage = "https://github.com/crispgm/gsm"
14
+ spec.license = "MIT"
15
+
16
+ spec.required_ruby_version = '>= 2.3.0'
17
+
18
+ spec.files = `git ls-files -z`.split("\x0")
19
+ spec.bindir = "exe"
20
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
21
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
22
+ spec.require_paths = ["lib"]
23
+
24
+ spec.add_development_dependency "minitest"
25
+ spec.add_development_dependency "shoulda-context"
26
+ spec.add_development_dependency "codeclimate-test-reporter"
27
+
28
+ spec.add_dependency "mercenary", "~> 0.3.6"
29
+ end
@@ -0,0 +1,6 @@
1
+ module Gsm
2
+ require "gsm/bundle"
3
+ require "gsm/gem"
4
+ require "gsm/util"
5
+ require "gsm/version"
6
+ end
@@ -0,0 +1,14 @@
1
+ module Gsm
2
+ class Bundle
3
+
4
+ RUBY_GEM_URL = "https://rubygems.org/".freeze
5
+
6
+ def self.mirror(dst_url, src_url = RUBY_GEM_URL)
7
+ `bundle config mirror.#{src_url} #{dst_url}`
8
+ end
9
+
10
+ def self.reset
11
+ self.mirror(RUBY_GEM_URL)
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,178 @@
1
+ module Gsm
2
+ class Gem
3
+ require "yaml"
4
+
5
+ attr_reader :conf_path, :name_pivot
6
+ attr_reader :sources
7
+ attr_reader :use_name
8
+
9
+ MAX_GENERATED_NAMES = 11
10
+ GEMSTONE_NAMES = [
11
+ "Amethyst",
12
+ "Emerald",
13
+ "Chrysocolla",
14
+ "Hematite",
15
+ "Jasper",
16
+ "Malachite",
17
+ "Quartz",
18
+ "Ruby",
19
+ "Sapphire",
20
+ "Sugilite",
21
+ "Turquoise"
22
+ ].freeze
23
+
24
+ def initialize(conf_path)
25
+ @sources = Hash.new
26
+ @use_name = ""
27
+ @name_pivot = 0
28
+ @conf_path = conf_path
29
+
30
+ if !load_from_yaml?
31
+ # load from `gem sources`
32
+ load
33
+ end
34
+ save
35
+ end
36
+
37
+ def load(mock = nil)
38
+ if mock != nil
39
+ outputs = mock
40
+ else
41
+ outputs = `gem sources -l`
42
+ end
43
+ outputs.split("\n").each do |line|
44
+ line.strip!
45
+ if validate_url?(line)
46
+ if @sources.length >= MAX_GENERATED_NAMES
47
+ return false
48
+ end
49
+ name = generate_name
50
+ @sources[name] = line
51
+ end
52
+ end
53
+ end
54
+
55
+ def add(name, url)
56
+ return false if validate_name?(name)
57
+
58
+ # validate url
59
+ if !validate_url?(url)
60
+ return false
61
+ end
62
+
63
+ @sources[name] = url
64
+ save
65
+
66
+ name
67
+ end
68
+
69
+ def del(name)
70
+ return false if @use_name.eql?(name)
71
+ return nil if !@sources.has_key?(name)
72
+
73
+ @sources.delete(name)
74
+ save
75
+
76
+ name
77
+ end
78
+
79
+ def get
80
+ @use_name
81
+ end
82
+
83
+ def reset
84
+ @use_name.clear
85
+ @sources.clear
86
+ save
87
+ end
88
+
89
+ def use(name)
90
+ return false if !@sources.has_key?(name)
91
+ return @use_name if @use_name.eql?(name)
92
+
93
+ if !apply_source(name)
94
+ return false
95
+ end
96
+
97
+ @use_name = name
98
+ save
99
+
100
+ @use_name
101
+ end
102
+
103
+ def save
104
+ data = {
105
+ :use => @use_name,
106
+ :sources => @sources
107
+ }
108
+ # write to file
109
+ f = File.new(@conf_path, "w")
110
+ f.syswrite(data.to_yaml)
111
+ f.close
112
+ end
113
+
114
+ def to_s
115
+ return @sources[@use_name] if @sources.has_key?(@use_name)
116
+ end
117
+
118
+ private
119
+ def apply_source(name)
120
+ outputs = `gem sources -l`
121
+ outputs.split("\n").each do |line|
122
+ line.strip!
123
+ if validate_url?(line)
124
+ `gem sources --remove #{line}`
125
+ end
126
+ end
127
+
128
+ url = @sources[name]
129
+ output = `gem sources --add #{url}`
130
+ output.include?("#{url} added to sources")
131
+ end
132
+
133
+ private
134
+ def validate_name?(name)
135
+ return false if %r{[a-zA-Z]{1,32}*} =~ name
136
+ return false if @sources.has_key?(name)
137
+ true
138
+ end
139
+
140
+ private
141
+ def validate_url?(url)
142
+ url.start_with?("http://") || url.start_with?("https://") ? true : false
143
+ end
144
+
145
+ private
146
+ def load_from_yaml?
147
+ # read yaml
148
+ if File.exist?(@conf_path)
149
+ data = YAML.load_file(@conf_path)
150
+ @use_name = data[:use] if data.has_key?(:use)
151
+ @sources = data[:sources] if data.has_key?(:sources)
152
+ true
153
+ else
154
+ f = File.new(@conf_path, "w")
155
+ f.close
156
+ false
157
+ end
158
+ end
159
+
160
+ private
161
+ def generate_name
162
+ gen_name = ""
163
+
164
+ while @name_pivot < MAX_GENERATED_NAMES
165
+ gen_name = GEMSTONE_NAMES[@name_pivot].to_s
166
+
167
+ @name_pivot = @name_pivot + 1
168
+
169
+ if !@sources.has_key?(gen_name)
170
+ return gen_name
171
+ end
172
+ end
173
+
174
+ return false
175
+ end
176
+
177
+ end
178
+ end