hotreload 0.1.0
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/hotreload +5 -0
- data/lib/config.rb +27 -0
- data/lib/file_watcher.rb +33 -0
- data/lib/hotreload.rb +140 -0
- data/lib/main.rb +8 -0
- data/lib/server.rb +90 -0
- data/lib/signer.rb +14 -0
- metadata +108 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: c06e1f69e44e90bdb80283e3d314cedf32b43e1c
|
4
|
+
data.tar.gz: 71b80d3601f4fb729d2d8b73c30a6d445bfc605d
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: c7d524e36dd65e25eb4ef488225bfc86c8a05b64f485194d000ffd4f73f5f17db8072993c4954953fe1ecfd9e8f1e5bf141f0d8152c9a1ae34de5f291b776686
|
7
|
+
data.tar.gz: 5ad1d92fafe72204fcb20ce1c4030f4f858795d814e251b11d5f99162b4a6ec75215945adb8696c4d0d501b3507622ef4ea918253068293d0d16eb68a5277747
|
data/bin/hotreload
ADDED
data/lib/config.rb
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
module Config
|
2
|
+
PORT = 8898
|
3
|
+
HOST = '127.0.0.1'
|
4
|
+
CLIENT_NUM = 1
|
5
|
+
HOTRELOAD_KEY = 'bvijkijyhbt73jdk83ljbbzcfbbvvq'
|
6
|
+
end
|
7
|
+
|
8
|
+
# Command
|
9
|
+
module Command
|
10
|
+
# responses from client
|
11
|
+
InjectionComplete = 0
|
12
|
+
InjectionPause = 1
|
13
|
+
InjectionSign = 2
|
14
|
+
InjectionError = 3
|
15
|
+
|
16
|
+
# commands to Client
|
17
|
+
InjectionProject = 4
|
18
|
+
InjectionLog = 5
|
19
|
+
InjectionSigned = 6
|
20
|
+
InjectionLoad = 7
|
21
|
+
InjectionInject = 8
|
22
|
+
InjectionXprobe = 9
|
23
|
+
InjectionEval = 10
|
24
|
+
InjectionVaccineSettingChanged = 11
|
25
|
+
|
26
|
+
InjectionEOF = ~0
|
27
|
+
end
|
data/lib/file_watcher.rb
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'listen'
|
2
|
+
|
3
|
+
class FileWatcher
|
4
|
+
def initialize(path)
|
5
|
+
@path = path
|
6
|
+
@listener = nil
|
7
|
+
end
|
8
|
+
|
9
|
+
def startWatcher
|
10
|
+
if File.directory?(@path) == false
|
11
|
+
@path = File.dirname(@path)
|
12
|
+
if File.directory?(@path)
|
13
|
+
puts "watcher path not exist: #{@path}"
|
14
|
+
return
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
@listener = Listen.to(@path, only: onlyReg) do |modified, added, removed|
|
19
|
+
modified.each { |path| path.force_encoding('utf-8') }
|
20
|
+
yield(modified) unless modified.empty?
|
21
|
+
# added.each { |path| path.force_encoding('utf-8') }
|
22
|
+
# removed.each { |path| path.force_encoding('utf-8') }
|
23
|
+
end
|
24
|
+
|
25
|
+
@listener.start
|
26
|
+
sleep
|
27
|
+
end
|
28
|
+
|
29
|
+
def onlyReg
|
30
|
+
/\.m$/
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
data/lib/hotreload.rb
ADDED
@@ -0,0 +1,140 @@
|
|
1
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
2
|
+
#!/usr/bin/ruby -w
|
3
|
+
# -*- coding : utf-8 -*-
|
4
|
+
require 'server'
|
5
|
+
require 'config'
|
6
|
+
require 'file_watcher'
|
7
|
+
require 'signer'
|
8
|
+
include Config
|
9
|
+
include Command
|
10
|
+
|
11
|
+
class HotReload
|
12
|
+
def self.test(path)
|
13
|
+
puts "success, path is #{path}"
|
14
|
+
end
|
15
|
+
|
16
|
+
def initialize
|
17
|
+
@projectInjected = Hash.new
|
18
|
+
@pending = []
|
19
|
+
end
|
20
|
+
|
21
|
+
def startServer(projectpath)
|
22
|
+
@projectPath = File.expand_path("..", projectpath)
|
23
|
+
@server = Server.new
|
24
|
+
@server.run
|
25
|
+
|
26
|
+
# get current dir
|
27
|
+
@server.sendMessage(@projectPath)
|
28
|
+
|
29
|
+
# tell client the project being watched
|
30
|
+
projectfile = "#{@projectPath}/*.xcworkspace"
|
31
|
+
files_sorted_by_time = Dir[projectfile].sort_by{ |f| File.mtime(f) }
|
32
|
+
projectfile = files_sorted_by_time[0]
|
33
|
+
if projectfile == nil
|
34
|
+
projectfile = "#{@projectPath}/*.xcodeproj"
|
35
|
+
files_sorted_by_time = Dir[projectfile].sort_by{ |f| File.mtime(f) }
|
36
|
+
projectfile = files_sorted_by_time[0]
|
37
|
+
end
|
38
|
+
|
39
|
+
if readMessage != Config::HOTRELOAD_KEY
|
40
|
+
puts "not the validate client"
|
41
|
+
return
|
42
|
+
end
|
43
|
+
|
44
|
+
# client spcific data for building
|
45
|
+
frameworkPath = readMessage
|
46
|
+
arch = readMessage
|
47
|
+
|
48
|
+
@lastInjected = @projectInjected[projectfile]
|
49
|
+
if @lastInjected == nil
|
50
|
+
@lastInjected = Hash.new
|
51
|
+
@projectInjected[projectfile] = @lastInjected
|
52
|
+
end
|
53
|
+
|
54
|
+
executable = readMessage
|
55
|
+
if executable != nil
|
56
|
+
executableBuild = File.mtime(executable).tv_sec
|
57
|
+
@lastInjected.each do |key, value|
|
58
|
+
if File.extname(key) != ".storyboard" && File.extname(key) != "xib" && File.mtime(key).tv_sec > executable
|
59
|
+
inject(key)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
else
|
63
|
+
return
|
64
|
+
end
|
65
|
+
|
66
|
+
listenCommand
|
67
|
+
|
68
|
+
setProject(projectfile)
|
69
|
+
|
70
|
+
@watcher = nil
|
71
|
+
|
72
|
+
end
|
73
|
+
|
74
|
+
def readInt
|
75
|
+
@server.readInt
|
76
|
+
end
|
77
|
+
|
78
|
+
def readMessage
|
79
|
+
@server.readMessage
|
80
|
+
end
|
81
|
+
|
82
|
+
def inject(source)
|
83
|
+
Thread.new do
|
84
|
+
@server.sendCommand(Command::InjectionInject, source)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def changeFiles(changeFiles)
|
89
|
+
now = Time.now.to_i
|
90
|
+
changeFiles.each do |file|
|
91
|
+
unless @pending.include?(file)
|
92
|
+
time = @lastInjected[file]
|
93
|
+
if time == nil || now > time
|
94
|
+
@lastInjected[file] = now
|
95
|
+
@pending.push(file)
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
@pending.each do |file|
|
101
|
+
inject(file)
|
102
|
+
end
|
103
|
+
@pending.clear
|
104
|
+
|
105
|
+
end
|
106
|
+
|
107
|
+
def setProject(projectFile)
|
108
|
+
@server.sendCommand(Command::InjectionProject, projectFile)
|
109
|
+
# /Users/shantj/Documents/workspace/third/injection
|
110
|
+
@watcher = FileWatcher.new(@projectPath)
|
111
|
+
# @watcher = FileWatcher.new('/Users/shantj/Documents/workspace/third/injection') TODO
|
112
|
+
@watcher.startWatcher do |file|
|
113
|
+
changeFiles(file)
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
def listenCommand
|
118
|
+
Thread.new do
|
119
|
+
while (command = readInt) != Command::InjectionEOF
|
120
|
+
case command
|
121
|
+
when Command::InjectionComplete
|
122
|
+
puts "Injection Complete"
|
123
|
+
when Command::InjectionPause
|
124
|
+
when Command::InjectionSign
|
125
|
+
dylib = readMessage
|
126
|
+
signer = Signer.new
|
127
|
+
ret = signer.codeSignDylib(dylib)
|
128
|
+
@server.sendCommand(Command::InjectionSigned, ret ? '1' : '0')
|
129
|
+
when Command::InjectionError
|
130
|
+
puts "Injection error: #{readMessage}"
|
131
|
+
else
|
132
|
+
puts "InjectionServer: Unexpected case #{command}"
|
133
|
+
exit
|
134
|
+
end
|
135
|
+
end
|
136
|
+
puts "command end"
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
end
|
data/lib/main.rb
ADDED
data/lib/server.rb
ADDED
@@ -0,0 +1,90 @@
|
|
1
|
+
#!/usr/bin/ruby -w
|
2
|
+
# -*- coding : utf-8 -*-
|
3
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
4
|
+
require 'socket'
|
5
|
+
require 'config'
|
6
|
+
include Socket::Constants
|
7
|
+
include Config
|
8
|
+
|
9
|
+
class Server
|
10
|
+
def run
|
11
|
+
@server = Socket.new(AF_INET, SOCK_STREAM, 0)
|
12
|
+
sockaddr = Socket.sockaddr_in(Config::PORT, Config::HOST)
|
13
|
+
@server.bind(sockaddr)
|
14
|
+
@server.listen(1)
|
15
|
+
@client, _ = @server.accept
|
16
|
+
end
|
17
|
+
|
18
|
+
def stop
|
19
|
+
if @client != nil
|
20
|
+
@client.close
|
21
|
+
@client = nil
|
22
|
+
end
|
23
|
+
|
24
|
+
if @server != nil
|
25
|
+
@server.close
|
26
|
+
@server = nil
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def readInt
|
31
|
+
raise "client not connect #{@host}:#{@port}, please check" if @client == nil
|
32
|
+
|
33
|
+
begin
|
34
|
+
message = @client.recvfrom(4)[0]
|
35
|
+
msgInt = message.unpack("L")[0]
|
36
|
+
rescue StandardError => e
|
37
|
+
puts e.message
|
38
|
+
puts e.backtrace.inspect
|
39
|
+
end
|
40
|
+
|
41
|
+
msgInt
|
42
|
+
end
|
43
|
+
|
44
|
+
def readMessage
|
45
|
+
raise "client not connect #{@host}:#{@port}, please check" if @client == nil
|
46
|
+
|
47
|
+
begin
|
48
|
+
len = readInt
|
49
|
+
if len == ~0
|
50
|
+
return nil
|
51
|
+
end
|
52
|
+
|
53
|
+
message = @client.recvfrom(len)[0]
|
54
|
+
rescue StandardError => e
|
55
|
+
puts e.message
|
56
|
+
puts e.backtrace.inspect
|
57
|
+
end
|
58
|
+
|
59
|
+
message
|
60
|
+
end
|
61
|
+
|
62
|
+
def sendMessage(msg)
|
63
|
+
raise "client not connect #{@host}:#{@port}, please check" if @client == nil
|
64
|
+
|
65
|
+
begin
|
66
|
+
@client.write([msg.bytesize].pack("L"))
|
67
|
+
@client.write(msg)
|
68
|
+
rescue StandardError => e
|
69
|
+
puts e.message
|
70
|
+
puts e.backtrace.inspect
|
71
|
+
end
|
72
|
+
|
73
|
+
true
|
74
|
+
end
|
75
|
+
|
76
|
+
def sendCommand(command, msg)
|
77
|
+
raise "client not connect #{@host}:#{@port}, please check" if @client == nil
|
78
|
+
|
79
|
+
begin
|
80
|
+
@client.write([command].pack("L"))
|
81
|
+
sendMessage(msg)
|
82
|
+
rescue StandardError => e
|
83
|
+
puts e.message
|
84
|
+
puts e.backtrace.inspect
|
85
|
+
end
|
86
|
+
|
87
|
+
true
|
88
|
+
end
|
89
|
+
|
90
|
+
end
|
data/lib/signer.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
class Signer
|
2
|
+
# sign the dynamic library
|
3
|
+
#
|
4
|
+
# @param dylib the dylib's path
|
5
|
+
#
|
6
|
+
# @return true or false
|
7
|
+
#
|
8
|
+
def codeSignDylib(dylib)
|
9
|
+
command = "export CODESIGN_ALLOCATE=/Applications/Xcode.app"
|
10
|
+
"/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/codesign_allocate; "
|
11
|
+
"/usr/bin/codesign --force -s '-' '#{dylib}'"
|
12
|
+
system(command)
|
13
|
+
end
|
14
|
+
end
|
metadata
ADDED
@@ -0,0 +1,108 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: hotreload
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- shantj
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2019-05-23 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.17'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.17'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '10.0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '10.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '3.0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '3.0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: listen
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - '='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 3.1.5
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - '='
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: 3.1.5
|
69
|
+
description: hot reload changed files
|
70
|
+
email:
|
71
|
+
- 405812883@qq.com
|
72
|
+
executables:
|
73
|
+
- hotreload
|
74
|
+
extensions: []
|
75
|
+
extra_rdoc_files: []
|
76
|
+
files:
|
77
|
+
- bin/hotreload
|
78
|
+
- lib/config.rb
|
79
|
+
- lib/file_watcher.rb
|
80
|
+
- lib/hotreload.rb
|
81
|
+
- lib/main.rb
|
82
|
+
- lib/server.rb
|
83
|
+
- lib/signer.rb
|
84
|
+
homepage: https://github.com/shantj/hotreload.git
|
85
|
+
licenses:
|
86
|
+
- MIT
|
87
|
+
metadata: {}
|
88
|
+
post_install_message:
|
89
|
+
rdoc_options: []
|
90
|
+
require_paths:
|
91
|
+
- lib
|
92
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
98
|
+
requirements:
|
99
|
+
- - ">="
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
version: '0'
|
102
|
+
requirements: []
|
103
|
+
rubyforge_project:
|
104
|
+
rubygems_version: 2.6.14
|
105
|
+
signing_key:
|
106
|
+
specification_version: 4
|
107
|
+
summary: hot reload changed files
|
108
|
+
test_files: []
|