runeblog 0.3.02

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.
Files changed (141) hide show
  1. checksums.yaml +7 -0
  2. data/README.lt3 +279 -0
  3. data/README.md +312 -0
  4. data/bin/blog +200 -0
  5. data/bin/mkwidget +164 -0
  6. data/data/EDITOR +1 -0
  7. data/data/ROOT +1 -0
  8. data/data/VIEW +1 -0
  9. data/data/features.txt +18 -0
  10. data/data/global.lt3 +20 -0
  11. data/data/universal.lt3 +18 -0
  12. data/empty_view/assets/austin-pano.jpg +0 -0
  13. data/empty_view/assets/sky2.jpg +0 -0
  14. data/empty_view/config/exper/2svg.lt3 +38 -0
  15. data/empty_view/config/exper/gen_svg.rb +60 -0
  16. data/empty_view/config/exper/meta.html +10 -0
  17. data/empty_view/config/exper/s2.html +25 -0
  18. data/empty_view/config/exper/varmint.rb +50 -0
  19. data/empty_view/config/facebook/credentials.txt +7 -0
  20. data/empty_view/config/facebook/facebook.rb +42 -0
  21. data/empty_view/config/facebook/fb.html +10 -0
  22. data/empty_view/config/facebook/fb.js.lt3 +15 -0
  23. data/empty_view/config/reddit/credentials.txt +6 -0
  24. data/empty_view/config/reddit/notes.txt +4 -0
  25. data/empty_view/config/reddit/reddit_post_url.py +34 -0
  26. data/empty_view/config/reddit/redpost.rb +43 -0
  27. data/empty_view/config/reddit/the-graffiti-wall.html +91 -0
  28. data/empty_view/config/twitter/credentials.txt +3 -0
  29. data/empty_view/config/twitter/tw.html +12 -0
  30. data/empty_view/config/twitter/tw.js +5 -0
  31. data/empty_view/config/twitter/twitter.rb +35 -0
  32. data/empty_view/posts/GIT_IS_DUMB +1 -0
  33. data/empty_view/remote/assets/GIT_IS_DUMB +1 -0
  34. data/empty_view/remote/banner/navbar/GIT_IS_DUMB +0 -0
  35. data/empty_view/remote/etc/GIT_IS_DUMB +1 -0
  36. data/empty_view/remote/permalink/GIT_IS_DUMB +1 -0
  37. data/empty_view/remote/widgets/ad/GIT_IS_DUMB +2 -0
  38. data/empty_view/remote/widgets/links/GIT_IS_DUMB +2 -0
  39. data/empty_view/remote/widgets/news/GIT_IS_DUMB +2 -0
  40. data/empty_view/remote/widgets/pages/GIT_IS_DUMB +2 -0
  41. data/empty_view/remote/widgets/pinned/GIT_IS_DUMB +2 -0
  42. data/empty_view/settings/features.txt +18 -0
  43. data/empty_view/settings/publish.txt +5 -0
  44. data/empty_view/settings/recent.txt +6 -0
  45. data/empty_view/settings/view.txt +4 -0
  46. data/empty_view/themes/standard/README +59 -0
  47. data/empty_view/themes/standard/banner/banner.lt3 +5 -0
  48. data/empty_view/themes/standard/banner/navbar/about.lt3 +18 -0
  49. data/empty_view/themes/standard/banner/navbar/contact.lt3 +18 -0
  50. data/empty_view/themes/standard/banner/navbar/faq.lt3 +1 -0
  51. data/empty_view/themes/standard/banner/navbar/list.data +3 -0
  52. data/empty_view/themes/standard/banner/top.lt3 +20 -0
  53. data/empty_view/themes/standard/blog/generate.lt3 +21 -0
  54. data/empty_view/themes/standard/blog/head.lt3 +16 -0
  55. data/empty_view/themes/standard/blog/index.lt3 +17 -0
  56. data/empty_view/themes/standard/blog/post_entry.lt3 +21 -0
  57. data/empty_view/themes/standard/etc/blog.css.lt3 +62 -0
  58. data/empty_view/themes/standard/etc/externals.lt3 +24 -0
  59. data/empty_view/themes/standard/etc/favicon.ico +0 -0
  60. data/empty_view/themes/standard/etc/misc.js +20 -0
  61. data/empty_view/themes/standard/post/generate.lt3 +38 -0
  62. data/empty_view/themes/standard/post/head.lt3 +7 -0
  63. data/empty_view/themes/standard/post/index.lt3 +24 -0
  64. data/empty_view/themes/standard/post/permalink.lt3 +32 -0
  65. data/empty_view/themes/standard/widgets/README +4 -0
  66. data/empty_view/themes/standard/widgets/ad/ad.lt3 +22 -0
  67. data/empty_view/themes/standard/widgets/ad/ad1.png +0 -0
  68. data/empty_view/themes/standard/widgets/ad/ad2.png +0 -0
  69. data/empty_view/themes/standard/widgets/ad/ad3.png +0 -0
  70. data/empty_view/themes/standard/widgets/ad/ad4.png +0 -0
  71. data/empty_view/themes/standard/widgets/bydates/README +2 -0
  72. data/empty_view/themes/standard/widgets/bydates/bydates.rb +18 -0
  73. data/empty_view/themes/standard/widgets/bydates/card.css +1 -0
  74. data/empty_view/themes/standard/widgets/bydates/custom.rb +1 -0
  75. data/empty_view/themes/standard/widgets/bydates/main.css +2 -0
  76. data/empty_view/themes/standard/widgets/links/README +2 -0
  77. data/empty_view/themes/standard/widgets/links/card.css +1 -0
  78. data/empty_view/themes/standard/widgets/links/custom.rb +1 -0
  79. data/empty_view/themes/standard/widgets/links/links.rb +90 -0
  80. data/empty_view/themes/standard/widgets/links/list.data +3 -0
  81. data/empty_view/themes/standard/widgets/links/main.css +2 -0
  82. data/empty_view/themes/standard/widgets/news/README +2 -0
  83. data/empty_view/themes/standard/widgets/news/card.css +1 -0
  84. data/empty_view/themes/standard/widgets/news/custom.rb +1 -0
  85. data/empty_view/themes/standard/widgets/news/list.data +4 -0
  86. data/empty_view/themes/standard/widgets/news/main.css +2 -0
  87. data/empty_view/themes/standard/widgets/news/news.rb +88 -0
  88. data/empty_view/themes/standard/widgets/pages/README +2 -0
  89. data/empty_view/themes/standard/widgets/pages/card.css +1 -0
  90. data/empty_view/themes/standard/widgets/pages/custom.rb +1 -0
  91. data/empty_view/themes/standard/widgets/pages/disclaim.lt3 +10 -0
  92. data/empty_view/themes/standard/widgets/pages/faq.lt3 +40 -0
  93. data/empty_view/themes/standard/widgets/pages/like-dislike.lt3 +11 -0
  94. data/empty_view/themes/standard/widgets/pages/list.data +4 -0
  95. data/empty_view/themes/standard/widgets/pages/local.rb +0 -0
  96. data/empty_view/themes/standard/widgets/pages/main.css +2 -0
  97. data/empty_view/themes/standard/widgets/pages/other-stuff.lt3 +10 -0
  98. data/empty_view/themes/standard/widgets/pages/pages.rb +95 -0
  99. data/empty_view/themes/standard/widgets/pinned/README +2 -0
  100. data/empty_view/themes/standard/widgets/pinned/card.css +1 -0
  101. data/empty_view/themes/standard/widgets/pinned/custom.rb +1 -0
  102. data/empty_view/themes/standard/widgets/pinned/main.css +2 -0
  103. data/empty_view/themes/standard/widgets/pinned/pinned.rb +99 -0
  104. data/empty_view/themes/standard/widgets/search/README +2 -0
  105. data/empty_view/themes/standard/widgets/search/card.css +1 -0
  106. data/empty_view/themes/standard/widgets/search/custom.rb +1 -0
  107. data/empty_view/themes/standard/widgets/search/main.css +2 -0
  108. data/empty_view/themes/standard/widgets/search/search.rb +18 -0
  109. data/empty_view/themes/standard/widgets/sitemap/README +2 -0
  110. data/empty_view/themes/standard/widgets/sitemap/card.css +1 -0
  111. data/empty_view/themes/standard/widgets/sitemap/custom.rb +1 -0
  112. data/empty_view/themes/standard/widgets/sitemap/main.css +2 -0
  113. data/empty_view/themes/standard/widgets/sitemap/sitemap.rb +18 -0
  114. data/empty_view/themes/standard/widgets/tag-cloud/OLD-example.lt3 +12 -0
  115. data/empty_view/themes/standard/widgets/tag-cloud/README +2 -0
  116. data/empty_view/themes/standard/widgets/tag-cloud/card.css +1 -0
  117. data/empty_view/themes/standard/widgets/tag-cloud/custom.rb +1 -0
  118. data/empty_view/themes/standard/widgets/tag-cloud/main.css +2 -0
  119. data/empty_view/themes/standard/widgets/tag-cloud/tag-cloud.lt3 +3 -0
  120. data/empty_view/themes/standard/widgets/tag-cloud/tag-cloud.rb +18 -0
  121. data/lib/Javascript.stuff +69 -0
  122. data/lib/helpers-blog.rb +155 -0
  123. data/lib/helpers-repl.rb +201 -0
  124. data/lib/liveblog.rb +825 -0
  125. data/lib/logging.rb +44 -0
  126. data/lib/lowlevel.rb +73 -0
  127. data/lib/pathmagic.rb +14 -0
  128. data/lib/post.rb +211 -0
  129. data/lib/processing.rb +60 -0
  130. data/lib/publish.rb +73 -0
  131. data/lib/repl.rb +597 -0
  132. data/lib/runeblog.rb +773 -0
  133. data/lib/runeblog_version.rb +50 -0
  134. data/lib/view.rb +69 -0
  135. data/runeblog.gemspec +42 -0
  136. data/test/austin.rb +158 -0
  137. data/test/fakeimage.jpg +0 -0
  138. data/test/general_test.rb +304 -0
  139. data/test/make_blog.rb +196 -0
  140. data/test/test +3 -0
  141. metadata +242 -0
@@ -0,0 +1,44 @@
1
+ unless self.respond_to?("log!")
2
+ $logging = true
3
+ $log = File.new("/tmp/runeblog.log","w")
4
+
5
+ def outlog(str = "", stderr: false)
6
+ $log.puts str
7
+ STDERR.puts str if stderr
8
+ end
9
+
10
+ def log!(str: "", enter: nil, args: [], pwd: false, dir: false, level: 0, stderr: false)
11
+ return unless $logging
12
+ @err_level ||= ENV['RUNEBLOG_ERROR_LEVEL']
13
+ @err_level ||= 0
14
+ return if level < @err_level
15
+
16
+ time = Time.now.strftime("%H:%M:%S")
17
+
18
+ meth = ""
19
+ meth = "#{enter}" if enter
20
+
21
+ para = "(#{args.inspect[1..-2]})"
22
+
23
+ source = caller[0].sub(/.*\//, " in ").sub(/:/, " line ").sub(/:.*/, "")
24
+ source = "in #{source} (probably liveblog.rb)" if source.include? "(eval)"
25
+
26
+ str = " ... #{str}" unless str.empty?
27
+ indent = " "*12
28
+
29
+ outlog "#{time} #{meth}#{para}"
30
+ outlog "#{indent} #{str} " unless str.empty?
31
+ outlog "#{indent} #{source}"
32
+ outlog "#{indent} pwd = #{Dir.pwd} " if pwd
33
+ if dir
34
+ files = (Dir.entries('.') - %w[. ..]).join(" ")
35
+ outlog "#{indent} dir/* = #{files}"
36
+ end
37
+ # outlog "#{indent} livetext params = #{livedata.inpect} " unless livedata.nil?
38
+ outlog
39
+ $log.close
40
+ $log = File.new("/tmp/runeblog.log","a")
41
+ end
42
+
43
+ end
44
+
@@ -0,0 +1,73 @@
1
+
2
+ def dump(obj, name)
3
+ File.write(name, obj)
4
+ end
5
+
6
+ def system!(str, show: false)
7
+ log!(enter: __method__, args: [str], level: 2)
8
+ STDERR.puts str if show
9
+ rc = system(str)
10
+ return rc if rc
11
+ STDERR.puts "FAILED: #{str.inspect}"
12
+ STDERR.puts "\ncaller = \n#{caller.join("\n ")}\n"
13
+ if defined?(RubyText)
14
+ sleep 6
15
+ RubyText.stop
16
+ exit
17
+ end
18
+ return rc
19
+ end
20
+
21
+ def _get_data?(file) # File need not exist
22
+ if File.exist?(file)
23
+ _get_data(file)
24
+ else
25
+ []
26
+ end
27
+ end
28
+
29
+ def _get_data(file)
30
+ lines = File.readlines(file)
31
+ lines.reject! {|line| line[0] == "-" } # allow rejection of lines
32
+ lines = lines.map do |line|
33
+ line.sub(/ *# .*$/, "") # allow trailing comments
34
+ end
35
+ lines
36
+ end
37
+
38
+ def copy(src, dst)
39
+ log!(enter: __method__, args: [src, dst], level: 2)
40
+ cmd = "cp #{src} #{dst} 2>/dev/null"
41
+ system!(cmd)
42
+ end
43
+
44
+ def copy!(src, dst)
45
+ log!(enter: __method__, args: [src, dst], level: 2)
46
+ cmd = "cp -r #{src} #{dst} 2>/dev/null"
47
+ system!(cmd)
48
+ end
49
+
50
+ def create_dirs(*dirs)
51
+ log!(enter: __method__, args: [*dirs], level: 3)
52
+ dirs.each do |dir|
53
+ dir = dir.to_s # symbols allowed
54
+ next if Dir.exist?(dir)
55
+ cmd = "mkdir -p #{dir} >/dev/null"
56
+ result = system!(cmd)
57
+ raise CantCreateDir(dir) unless result
58
+ end
59
+ end
60
+
61
+ def interpolate(str, bind)
62
+ log!(enter: __method__, args: [str, bind], level: 3)
63
+ wrap = "<<-EOS\n#{str}\nEOS"
64
+ eval wrap, bind
65
+ end
66
+
67
+ def error(err)
68
+ log!(str: err, enter: __method__, args: [err], level: 2)
69
+ str = "\n Error: #{err}"
70
+ puts str
71
+ puts err.backtrace.join("\n")
72
+ end
73
+
@@ -0,0 +1,14 @@
1
+ module PathSep
2
+ def /(right)
3
+ s1 = self.to_s.dup
4
+ s2 = right.to_s.dup
5
+ s1 << "/" unless s1.end_with?("/") || s2.start_with?("/")
6
+ path = s1 + s2
7
+ path.gsub!("//", "/")
8
+ path
9
+ end
10
+ end
11
+
12
+ String.include(PathSep)
13
+ Symbol.include(PathSep)
14
+
@@ -0,0 +1,211 @@
1
+ require 'runeblog'
2
+ require 'pathmagic'
3
+
4
+ class RuneBlog::Post
5
+
6
+ attr_reader :num, :title, :date, :views, :num, :slug
7
+ attr_accessor :meta, :blog, :draft
8
+
9
+ include RuneBlog::Helpers
10
+
11
+
12
+ def self.load(post)
13
+ log!(enter: __method__, args: [post], level: 3)
14
+ raise "Doesn't work right now"
15
+ raise NoBlogAccessor if RuneBlog.blog.nil?
16
+ # "post" is a slug
17
+ pdir = RuneBlog.blog.root/:drafts/post
18
+ meta = nil
19
+ Dir.chdir(pdir) do
20
+ meta = read_config("metadata.txt")
21
+ meta.date = Date.parse(meta.date)
22
+ meta.views = meta.views.split
23
+ meta.tags = meta.tags.split
24
+ meta.teaser = File.read("teaser.txt")
25
+ # meta.body = File.read("body.txt")
26
+ end
27
+ meta
28
+ end
29
+
30
+ def write_metadata(meta) # FIXME ???
31
+ log!(enter: __method__, args: [meta], level: 3)
32
+ debug "=== write_metadata:"
33
+ debug "-----\n#{meta.inspect}\n-----"
34
+ fname2 = "metadata.txt"
35
+ hash = meta.to_h
36
+
37
+ File.write("teaser.txt", hash[:teaser])
38
+ hash.delete(:teaser)
39
+ hash.delete(:body)
40
+
41
+ hash[:views] = hash[:views].join(" ")
42
+ hash[:tags] = hash[:tags].join(" ")
43
+
44
+ fields = [:num, :title, :date, :pubdate, :views, :tags]
45
+
46
+ f2 = File.new(fname2, "w")
47
+ fields.each {|fld| f2.puts "#{fld}: #{hash[fld]}" }
48
+ f2.close
49
+ end
50
+
51
+ def initialize
52
+ log!(enter: __method__, level: 3)
53
+ @blog = RuneBlog.blog || raise(NoBlogAccessor)
54
+ @meta = OpenStruct.new
55
+ end
56
+
57
+ def self.create(title:, teaser:, body:, pubdate: Time.now.strftime("%Y-%m-%d"),
58
+ views:[], file: nil)
59
+ log!(enter: __method__, args: [title, teaser, body, pubdate, views], stderr: true)
60
+ post = self.new
61
+ # NOTE: This is the ONLY place next_sequence is called!
62
+ num = post.meta.num = post.blog.next_sequence
63
+
64
+ # new_metadata
65
+ post.meta.title, post.meta.teaser, post.meta.body, post.meta.pubdate =
66
+ title, teaser, body, pubdate
67
+ post.meta.views = [post.blog.view.to_s] + views
68
+ post.meta.tags = []
69
+ post.blog.make_slug(post.meta) # adds to meta
70
+
71
+ # create_draft
72
+ viewhome = post.blog.view.publisher.url
73
+ meta = post.meta
74
+ if file.nil?
75
+ text = RuneBlog.post_template(num: meta.num, title: meta.title, date: meta.pubdate,
76
+ view: meta.view, teaser: meta.teaser, body: meta.body,
77
+ views: meta.views, tags: meta.tags, home: viewhome)
78
+ srcdir = post.blog.root/:drafts + "/"
79
+ vpdir = post.blog.root/:drafts + "/"
80
+ fname = meta.slug + ".lt3"
81
+ post.draft = srcdir + fname
82
+ dump(text, post.draft)
83
+ else
84
+ dump(File.read(file), post.draft)
85
+ end
86
+ return post
87
+ end
88
+
89
+ def edit
90
+ log!(enter: __method__)
91
+ result = system!("vi #@draft +8") # TODO improve this
92
+ raise EditorProblem(draft) unless result
93
+ nil
94
+ rescue => err
95
+ error(err)
96
+ end
97
+
98
+ def build
99
+ log!(enter: __method__)
100
+ post = self
101
+ views = post.meta.views
102
+ text = File.read(@draft)
103
+ @blog.generate_post(@draft)
104
+ end
105
+ end
106
+
107
+ class RuneBlog::ViewPost
108
+ attr_accessor :nslug, :aslug, :num, :view, :blog
109
+ attr_accessor :path, :title, :date, :teaser_text
110
+
111
+ def self.make(blog:, view:, nslug:)
112
+ raise "No numeric prefix on #{nslug}" unless nslug =~ /^\d{4}-/
113
+ raise "Not expecting an extension" if nslug.end_with?(".lt3") || nslug.end_with?(".html")
114
+ view = view.to_s
115
+ view.define_singleton_method :path do |subdir = ""|
116
+ str = blog.root/:views/view
117
+ str << "/#{subdir}" unless subdir.empty?
118
+ str
119
+ end
120
+ view.define_singleton_method :standard do |subdir = ""|
121
+ str = blog.root/:views/view/:themes/:standard
122
+ str << "/#{subdir}" unless subdir.empty?
123
+ str
124
+ end
125
+ view.define_singleton_method :postdir do |file = ""|
126
+ file = file.to_s
127
+ str = blog.root/:views/view/:posts/nslug
128
+ str = str/file unless file.empty?
129
+ str
130
+ end
131
+ view.define_singleton_method :remote do |dir: "", file: ""|
132
+ subdir = subdir.to_s
133
+ file = file.to_s
134
+ str = blog.root/:views/view/:remote
135
+ str = str/subdir unless subdir.empty?
136
+ str = str/file unless file.empty?
137
+ str
138
+ end
139
+ obj = RuneBlog::ViewPost.new(view, nslug)
140
+ obj.blog = blog
141
+ obj.view = view
142
+ obj.nslug = nslug
143
+ obj.aslug = nslug[5..-1]
144
+ obj.num = nslug[0..3]
145
+ obj
146
+ end
147
+
148
+ def repo(subdir = "")
149
+ subdir = subdir.to_s
150
+ unless subdir.empty?
151
+ raise "Expected 'posts' or 'drafts'" unless %w[posts drafts].include?(subdir)
152
+ end
153
+ str = blog.root
154
+ str = str/subdir unless subdir.empty?
155
+ str
156
+ end
157
+
158
+ alias root repo
159
+
160
+ def slug(num = true, ext = "")
161
+ ext = ext.to_s
162
+ str = ""
163
+ str << @num << "-" if num
164
+ str << @aslug
165
+ str << ext
166
+ str
167
+ end
168
+
169
+ =begin
170
+ aslug this-is-a-post
171
+ aslug_live this-is-a-post.lt3
172
+ aslug_html this-is-a-post.lt3
173
+ nslug 0001-this-is-a-post
174
+
175
+ slug(:num, ext = "")
176
+ =end
177
+
178
+ def initialize(view, postdir)
179
+ log!(enter: __method__, args: [view, postdir], level: 3)
180
+ # Assumes already parsed/processed
181
+ @blog = RuneBlog.blog || raise(NoBlogAccessor)
182
+ @path = postdir.dup
183
+ @nslug = @path.split("/").last
184
+ @aslug = @nslug[5..-1]
185
+ fname = "#{postdir}/teaser.txt" # ???
186
+ @teaser_text = File.read(fname).chomp
187
+ # FIXME dumb hacks...
188
+ mdfile = postdir/"metadata.txt"
189
+ lines = File.readlines(mdfile)
190
+ @title = lines.grep(/title:/).first[7..-1].chomp
191
+ @date = lines.grep(/pubdate:/).first[9..-1].chomp
192
+ # print "-- date = #{@date.inspect} "; gets
193
+ rescue => err
194
+ STDERR.puts "--- #{err}\n #{err.backtrace.join("\n ")}"
195
+ end
196
+
197
+ def get_dirs
198
+ log!(enter: __method__, args: [view, postdir], level: 3)
199
+ fname = File.basename(draft)
200
+ noext = fname.sub(/.lt3$/, "")
201
+ vdir = @root/:views/view
202
+ dir = vdir/:posts/noext + "/"
203
+ Dir.mkdir(dir) unless Dir.exist?(dir)
204
+ system!("cp #{draft} #{dir}")
205
+ viewdir, slugdir, aslug = vdir, dir, noext[5..-1]
206
+ theme = viewdir/:themes/:standard
207
+ [noext, viewdir, slugdir, aslug, theme]
208
+ end
209
+
210
+ end
211
+
@@ -0,0 +1,60 @@
1
+ if ! defined?(LIVE)
2
+
3
+ require 'livetext'
4
+
5
+ LIVE = Livetext.new
6
+ LEXT = ".lt3"
7
+
8
+ def newer?(f1, f2)
9
+ File.mtime(f1) > File.mtime(f2)
10
+ end
11
+
12
+ def stale?(src, dst, deps, force = false)
13
+ meh = File.new("/tmp/dammit-#{src.gsub(/\//, "-")}", "w")
14
+ log!(enter: __method__, args: [src, dst], level: 3)
15
+ raise "Source #{src} not found in #{Dir.pwd}" unless File.exist?(src)
16
+ return true if force
17
+ return true unless File.exist?(dst)
18
+ return true if newer?(src, dst)
19
+ deps.each {|dep| return true if newer?(dep, dst) }
20
+ return false
21
+ end
22
+
23
+ def preprocess(cwd: Dir.pwd, src:,
24
+ dst: nil, strip: false,
25
+ deps: [], copy: nil, debug: false, force: false,
26
+ mix: [], call: [], vars: {})
27
+ src += LEXT unless src.end_with?(LEXT)
28
+ if strip
29
+ dst = File.basename(src).sub(/.lt3$/,"")
30
+ else
31
+ dst += ".html" unless dst.end_with?(".html")
32
+ end
33
+ sp = " "*12
34
+ Dir.chdir(cwd) do
35
+ if debug
36
+ STDERR.puts "#{sp} -- preprocess "
37
+ STDERR.puts "#{sp} src: #{src}"
38
+ STDERR.puts "#{sp} dst: #{dst}"
39
+ STDERR.puts "#{sp} in: #{Dir.pwd}"
40
+ STDERR.puts "#{sp} from: #{caller[0]}"
41
+ STDERR.puts "#{sp} copy: #{copy}" if copy
42
+ end
43
+ stale = stale?(src, dst, deps, force)
44
+ if stale
45
+ live = Livetext.customize(mix: "liveblog", call: call, vars: vars)
46
+ out = live.xform_file(src)
47
+ File.write(dst, out)
48
+ system!("cp #{dst} #{copy}") if copy
49
+ end
50
+ puts "#{sp} -- ^ Already up to date!" if debug && ! stale
51
+ end
52
+ end
53
+
54
+ def get_live_vars(src)
55
+ live = Livetext.customize(call: [".nopara"])
56
+ live.xform_file(src)
57
+ live
58
+ end
59
+
60
+ end
@@ -0,0 +1,73 @@
1
+ if ! defined?(Already_publish)
2
+
3
+ Already_publish = nil
4
+
5
+ require 'pathmagic'
6
+ require 'processing'
7
+
8
+ class RuneBlog::Publishing
9
+ attr_reader :user, :server, :docroot, :path
10
+
11
+ BadRemoteLogin = Exception.new("Can't login remotely")
12
+ BadRemotePerms = Exception.new("Bad remote permissions")
13
+
14
+ def initialize(view)
15
+ log!(enter: __method__, args: [view.to_s])
16
+ @blog = RuneBlog.blog
17
+ dir = @blog.root/:views/view/"themes/standard/"
18
+ gfile = dir/"global.lt3"
19
+ return unless File.exist?(gfile) # FIXME Hackish as hell
20
+
21
+ live = get_live_vars(gfile)
22
+ @user = live.vars["publish.user"]
23
+ @server = live.vars["publish.server"]
24
+ @docroot = live.vars["publish.docroot"]
25
+ @path = live.vars["publish.path"]
26
+ @proto = live.vars["publish.proto"]
27
+ end
28
+
29
+ def to_h
30
+ log!(enter: __method__, level: 3)
31
+ {user: @user, server: @server, docroot: @docroot,
32
+ path: @path, proto: @proto}
33
+ end
34
+
35
+ def url
36
+ log!(enter: __method__, level: 3)
37
+ vname = @blog.view.name # .gsub(/_/, "\\_")
38
+ url = "#@proto://#@server/#@path" # /#{vname}"
39
+ end
40
+
41
+ def publish
42
+ log!(enter: __method__, level: 1)
43
+ dir = @docroot/@path
44
+ view_name = @blog.view.name
45
+ viewpath = dir # /view_name
46
+ # FIXME rsync doesn't work
47
+ cmd = "rsync -r -z #{@blog.root}/views/#{@blog.view}/remote/ #@user@#@server:#{viewpath}/"
48
+ system!(cmd)
49
+ dump("#{@blog.view} at #{Time.now}", "#{@blog.view.dir}/last_published")
50
+ true
51
+ end
52
+
53
+ def remote_login?
54
+ log!(enter: __method__)
55
+ cmd = "ssh -o BatchMode=yes #@user@#@server -x date >/dev/null 2>&1"
56
+ result = system(cmd)
57
+ return nil unless result
58
+ true
59
+ end
60
+
61
+ def remote_permissions?
62
+ log!(enter: __method__)
63
+ dir = @docroot/@path
64
+ temp = @path/"__only_testing"
65
+ try1 = system("ssh -o BatchMode=yes -o ConnectTimeout=1 #@user@#@server -x mkdir -p #{temp} >/dev/null 2>&1")
66
+ return nil unless try1
67
+ try2 = system("ssh -o BatchMode=yes -o ConnectTimeout=1 #@user@#@server -x rmdir #{temp} >/dev/null 2>&1")
68
+ return nil unless try2
69
+ true
70
+ end
71
+ end
72
+
73
+ end