vx-aptly 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (75) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +23 -0
  3. data/Dockerfile +11 -0
  4. data/Gemfile +4 -0
  5. data/LICENSE.txt +22 -0
  6. data/README.md +29 -0
  7. data/Rakefile +36 -0
  8. data/bin/vx-aptly +4 -0
  9. data/doc/aptly.example +16 -0
  10. data/doc/aptly.upstart +27 -0
  11. data/doc/cloud-files.example +9 -0
  12. data/docker/install.sh +47 -0
  13. data/docker/my_init +57 -0
  14. data/docker/supervisord.conf +17 -0
  15. data/lib/vx/aptly.rb +33 -0
  16. data/lib/vx/aptly/app.rb +194 -0
  17. data/lib/vx/aptly/cli.sh +116 -0
  18. data/lib/vx/aptly/config.ru +3 -0
  19. data/lib/vx/aptly/mixin/capture.rb +37 -0
  20. data/lib/vx/aptly/package.rb +110 -0
  21. data/lib/vx/aptly/public/404.html +153 -0
  22. data/lib/vx/aptly/public/css/animate.css +3158 -0
  23. data/lib/vx/aptly/public/css/bootstrap.min.css +5 -0
  24. data/lib/vx/aptly/public/css/flat-ui.css +6007 -0
  25. data/lib/vx/aptly/public/css/theme.css +131 -0
  26. data/lib/vx/aptly/public/fonts/glyphicons/flat-ui-icons-regular.eot +0 -0
  27. data/lib/vx/aptly/public/fonts/glyphicons/flat-ui-icons-regular.svg +126 -0
  28. data/lib/vx/aptly/public/fonts/glyphicons/flat-ui-icons-regular.ttf +0 -0
  29. data/lib/vx/aptly/public/fonts/glyphicons/flat-ui-icons-regular.woff +0 -0
  30. data/lib/vx/aptly/public/fonts/glyphicons/selection.json +2106 -0
  31. data/lib/vx/aptly/public/fonts/lato/lato-black.eot +0 -0
  32. data/lib/vx/aptly/public/fonts/lato/lato-black.svg +4691 -0
  33. data/lib/vx/aptly/public/fonts/lato/lato-black.ttf +0 -0
  34. data/lib/vx/aptly/public/fonts/lato/lato-black.woff +0 -0
  35. data/lib/vx/aptly/public/fonts/lato/lato-bold.eot +0 -0
  36. data/lib/vx/aptly/public/fonts/lato/lato-bold.svg +5085 -0
  37. data/lib/vx/aptly/public/fonts/lato/lato-bold.ttf +0 -0
  38. data/lib/vx/aptly/public/fonts/lato/lato-bold.woff +0 -0
  39. data/lib/vx/aptly/public/fonts/lato/lato-bolditalic.eot +0 -0
  40. data/lib/vx/aptly/public/fonts/lato/lato-bolditalic.svg +4514 -0
  41. data/lib/vx/aptly/public/fonts/lato/lato-bolditalic.ttf +0 -0
  42. data/lib/vx/aptly/public/fonts/lato/lato-bolditalic.woff +0 -0
  43. data/lib/vx/aptly/public/fonts/lato/lato-italic.eot +0 -0
  44. data/lib/vx/aptly/public/fonts/lato/lato-italic.svg +4514 -0
  45. data/lib/vx/aptly/public/fonts/lato/lato-italic.ttf +0 -0
  46. data/lib/vx/aptly/public/fonts/lato/lato-italic.woff +0 -0
  47. data/lib/vx/aptly/public/fonts/lato/lato-light.eot +0 -0
  48. data/lib/vx/aptly/public/fonts/lato/lato-light.svg +4691 -0
  49. data/lib/vx/aptly/public/fonts/lato/lato-light.ttf +0 -0
  50. data/lib/vx/aptly/public/fonts/lato/lato-light.woff +0 -0
  51. data/lib/vx/aptly/public/fonts/lato/lato-regular.eot +0 -0
  52. data/lib/vx/aptly/public/fonts/lato/lato-regular.svg +4691 -0
  53. data/lib/vx/aptly/public/fonts/lato/lato-regular.ttf +0 -0
  54. data/lib/vx/aptly/public/fonts/lato/lato-regular.woff +0 -0
  55. data/lib/vx/aptly/public/img/favicon.ico +0 -0
  56. data/lib/vx/aptly/public/js/app.js +12 -0
  57. data/lib/vx/aptly/public/js/jquery_ujs.js +446 -0
  58. data/lib/vx/aptly/repo.rb +161 -0
  59. data/lib/vx/aptly/repo_publish.rb +165 -0
  60. data/lib/vx/aptly/version.rb +5 -0
  61. data/lib/vx/aptly/views/index.erb +94 -0
  62. data/lib/vx/aptly/views/layout.erb +54 -0
  63. data/lib/vx/aptly/views/repo_publishes/new.erb +49 -0
  64. data/lib/vx/aptly/views/repos/edit.erb +17 -0
  65. data/lib/vx/aptly/views/repos/errors.erb +5 -0
  66. data/lib/vx/aptly/views/repos/form.erb +26 -0
  67. data/lib/vx/aptly/views/repos/new.erb +17 -0
  68. data/lib/vx/aptly/views/repos/packages.erb +51 -0
  69. data/lib/vx/aptly/views/repos/show.erb +66 -0
  70. data/spec/lib/repo_publish_spec.rb +60 -0
  71. data/spec/spec_helper.rb +13 -0
  72. data/spec/support/aptly.conf +0 -0
  73. data/spec/support/home.rb +39 -0
  74. data/vx-aptly.gemspec +32 -0
  75. metadata +263 -0
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 972eb4efd927c6f2cafc2aa79dd06d210e278218
4
+ data.tar.gz: 8a3b77d2d2e7b24a7c1f06cab4a213f4a9e53e66
5
+ SHA512:
6
+ metadata.gz: f863fba591f65aef108963498bb5529a0caac0438edebd5a15984a2c36e9ebb3e93a9d523949dae03a8d633f5d75791e893745fa0396caf68b64da1259349c34
7
+ data.tar.gz: e70bbf5dace301aac72c9ded914cf14a1e476cfcca61a988efdcde3b20cbf912b860232ade6d7805a999e5b21337b8b9e412fd010a4b121d8eab5b8606eb63e2
@@ -0,0 +1,23 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ lib/bundler/man
11
+ pkg
12
+ rdoc
13
+ spec/reports
14
+ test/tmp
15
+ test/version_tmp
16
+ tmp
17
+ *.bundle
18
+ *.so
19
+ *.o
20
+ *.a
21
+ mkmf.log
22
+ bower_components
23
+ *.tar
@@ -0,0 +1,11 @@
1
+ FROM ubuntu:14.04
2
+ MAINTAINER Dmitry Galinsky
3
+
4
+ ADD . /tmp/vx-aptly/
5
+ RUN bash /tmp/vx-aptly/docker/install.sh
6
+
7
+ VOLUME ["/data"]
8
+
9
+ EXPOSE 8080
10
+
11
+ CMD ["/my_init"]
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in vx-aptly-push.gemspec
4
+ gemspec
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Dmitry Galinsky
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,29 @@
1
+ # Vx::Aptly::Push
2
+
3
+ TODO: Write a gem description
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'vx-aptly-push'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install vx-aptly-push
18
+
19
+ ## Usage
20
+
21
+ TODO: Write usage instructions here
22
+
23
+ ## Contributing
24
+
25
+ 1. Fork it ( https://github.com/[my-github-username]/vx-aptly-push/fork )
26
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
27
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
28
+ 4. Push to the branch (`git push origin my-new-feature`)
29
+ 5. Create a new Pull Request
@@ -0,0 +1,36 @@
1
+ require 'rake'
2
+ require 'rake/testtask'
3
+ require "bundler/gem_tasks"
4
+
5
+ desc "Load gem environment"
6
+ task :environment do
7
+ require File.expand_path("../lib/vx/aptly", __FILE__)
8
+ end
9
+
10
+ namespace :docker do
11
+ desc "Build tagged docker image"
12
+ task build: :environment do
13
+ cmd = "docker build --rm -t vexor/aptly:#{Vx::Aptly::VERSION} ."
14
+ puts cmd
15
+ exec cmd
16
+ end
17
+
18
+ desc "Push docker image to index"
19
+ task push: :environment do
20
+ cmd = "docker push vexor/aptly:#{Vx::Aptly::VERSION} ."
21
+ puts cmd
22
+ exec cmd
23
+ end
24
+ end
25
+
26
+ desc "Run web server"
27
+ task :serve do
28
+ exec 'bin/vx-aptly serve'
29
+ end
30
+
31
+ Rake::TestTask.new :spec do |t|
32
+ t.libs.push "spec"
33
+ t.test_files = Dir.glob('spec/**/*_spec.rb')
34
+ end
35
+
36
+ task(default: :spec)
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ cli = File.expand_path("../../lib/vx/aptly/cli.sh", __FILE__)
4
+ exec "#{cli} #{ARGV.join(' ')}"
@@ -0,0 +1,16 @@
1
+ {
2
+ "rootDir": "/data/repo/.aptly",
3
+ "downloadConcurrency": 4,
4
+ "downloadSpeedLimit": 0,
5
+ "architectures": ["all", "i386", "amd64"],
6
+ "dependencyFollowSuggests": false,
7
+ "dependencyFollowRecommends": false,
8
+ "dependencyFollowAllVariants": false,
9
+ "dependencyFollowSource": false,
10
+ "gpgDisableSign": true,
11
+ "gpgDisableVerify": true,
12
+ "downloadSourcePackages": false,
13
+ "ppaDistributorID": "ubuntu",
14
+ "ppaCodename": "",
15
+ "S3PublishEndpoints": {}
16
+ }
@@ -0,0 +1,27 @@
1
+ description "VxAptly container"
2
+ author "Dmitry Galinsky"
3
+ start on filesystem and started docker
4
+ stop on runlevel [!2345]
5
+ respawn
6
+
7
+ env VERSION=0.9.0
8
+
9
+ pre-start script
10
+ set -x
11
+ set -e
12
+
13
+ i_version=$(docker inspect -f "{{ .Id }}" vexor/aptly:${VERSION})
14
+ c_version=$(docker inspect -f "{{ .Image }}" aptly)
15
+
16
+ if [ -n $i_version ] && [ -n $c_version ] && [ $i_version != $c_version ] ; then
17
+ docker stop aptly || true
18
+ docker rm -f aptly
19
+ fi
20
+
21
+ docker inspect aptly > /dev/null ||
22
+ docker create -e HTTPS=1 -e BASIC_AUTH=1 -p 0.0.0.0:443:8080 --name=aptly -v /data:/data vexor/aptly:${VERSION}
23
+ end script
24
+
25
+ script
26
+ /usr/bin/docker start -a aptly
27
+ end script
@@ -0,0 +1,9 @@
1
+ #!/bin/bash
2
+
3
+ set -e
4
+
5
+ export SDK_USERNAME=""
6
+ export SDK_API_KEY=""
7
+ export SDK_CONTAINER=""
8
+
9
+ cloud-files put -d -s ~/.aptly/public -d $SDK_CONTAINER
@@ -0,0 +1,47 @@
1
+ #!/bin/bash
2
+
3
+ set -e
4
+ set -x
5
+
6
+ cd /tmp/vx-aptly
7
+
8
+ # fix locales
9
+ locale-gen en_US.UTF-8
10
+ echo "LC_ALL=en_US.UTF-8" > /etc/default/locale
11
+ echo "LANG=en_US.UTF-8" >> /etc/default/locale
12
+
13
+ # install aptly
14
+ echo "deb http://repo.aptly.info/ squeeze main" >> /etc/apt/sources.list
15
+ gpg --keyserver keys.gnupg.net --recv-keys 2A194991
16
+ gpg -a --export 2A194991 | sudo apt-key add -
17
+ apt-get update -qq
18
+ apt-get install aptly=0.8 curl -qy
19
+
20
+ # create user
21
+ apt-get install passwd
22
+ useradd --no-create-home --home-dir /data/repo --shell /bin/bash repo
23
+
24
+ # install cloud files
25
+ curl --fail -s -L https://github.com/vexor/vx-binutils/releases/download/v0.2.1/vx-binutils_0.2.1-0_amd64.deb > /tmp/vx-binutils.deb
26
+ dpkg -i /tmp/vx-binutils.deb
27
+
28
+ # install vx-aptly
29
+ apt-get install git-core software-properties-common -qy
30
+ apt-add-repository -y ppa:brightbox/ruby-ng-experimental
31
+ apt-get update -qq
32
+ apt-get install ruby2.1 ruby2.1-dev build-essential libssl-dev -qy
33
+ gem update --system
34
+ gem build *.gemspec
35
+ gem install *.gem --no-ri --no-rdoc
36
+
37
+ # init
38
+ cp docker/my_init /my_init
39
+ chmod +x /my_init
40
+
41
+ # install supervisod
42
+ apt-get install supervisor python-pip -qy
43
+ pip install supervisor-stdout
44
+ cp docker/supervisord.conf /etc/supervisor/supervisord.conf
45
+
46
+ # Clean up APT when done.
47
+ apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
@@ -0,0 +1,57 @@
1
+ #!/bin/sh
2
+
3
+ set -e
4
+
5
+ export LC_ALL=en_US.UTF-8
6
+ export LANG=en_US.UTF-8
7
+
8
+ gem_root=$(vx-aptly root)
9
+
10
+ mkdir -p /data/repo
11
+ chown -R repo:repo /data/repo
12
+
13
+ test -d /data/repo/hooks || (
14
+ mkdir -p /data/repo/hooks
15
+ cp $gem_root/doc/cloud-files.example /data/repo/hooks/00_cloud-files.example
16
+ )
17
+
18
+ test -f /data/repo/.aptly.conf || (
19
+ cp $gem_root/doc/aptly.example /data/repo/.aptly.conf
20
+ )
21
+
22
+ test -f /data/repo/puma.key || (
23
+ openssl req \
24
+ -x509 \
25
+ -nodes \
26
+ -days 1826 \
27
+ -subj "/C=RU/L=Moscow/CN=$(hostname -f)" \
28
+ -newkey rsa:2048 \
29
+ -keyout /data/repo/puma.key \
30
+ -out /data/repo/puma.crt
31
+ )
32
+
33
+ test -f /data/repo/.token || (
34
+ user_passord=$(tr -cd '[:alnum:]' < /dev/urandom | fold -w40 | head -n1)
35
+ echo $user_passord > /data/repo/.token
36
+ )
37
+
38
+ test -f /data/repo/puma.rb || (
39
+ if [ "x$HTTPS" != "x" ] ; then
40
+ cat > /data/repo/puma.rb <<'EOL'
41
+ bind 'ssl://0.0.0.0:8080?key=/data/repo/puma.key&cert=/data/repo/puma.crt'
42
+ EOL
43
+ else
44
+ cat > /data/repo/puma.rb <<'EOL'
45
+ bind 'tcp://0.0.0.0:8080'
46
+ EOL
47
+ fi
48
+ )
49
+
50
+ export PYTHONUNBUFFERED=y
51
+ export RACK_ENV=production
52
+
53
+ if [ "x$BASIC_AUTH" != "x" ] ; then
54
+ export RACK_BASIC_AUTH=$(cat /data/repo/.token)
55
+ fi
56
+
57
+ exec /usr/bin/supervisord -c /etc/supervisor/supervisord.conf
@@ -0,0 +1,17 @@
1
+ [supervisord]
2
+ nodaemon=true
3
+
4
+ [program:puma]
5
+ command=/usr/local/bin/vx-aptly serve -C /data/repo/puma.rb
6
+ user=repo
7
+ group=repo
8
+ redirect_stderr=true
9
+ stdout_events_enabled=true
10
+ stderr_events_enabled=true
11
+ environment=HOME="/data/repo"
12
+
13
+ [eventlistener:stdout]
14
+ command = supervisor_stdout
15
+ buffer_size = 100
16
+ events = PROCESS_LOG
17
+ result_handler = supervisor_stdout:event_handler
@@ -0,0 +1,33 @@
1
+ require 'logger'
2
+
3
+ ::Logger.class_eval { alias :write :'<<' }
4
+
5
+ module Vx
6
+ module Aptly
7
+
8
+ class AptlyCommandError < Exception ; end
9
+ class PublishNotFoundError < Exception ; end
10
+
11
+ @@logger = ::Logger.new(STDOUT)
12
+ @@root = File.expand_path("../../../", __FILE__)
13
+
14
+ extend self
15
+
16
+ def logger
17
+ @@logger
18
+ end
19
+
20
+ def root
21
+ @@root
22
+ end
23
+
24
+ end
25
+ end
26
+
27
+ require File.expand_path("../aptly/version", __FILE__)
28
+ require File.expand_path("../aptly/mixin/capture", __FILE__)
29
+ require File.expand_path("../aptly/app", __FILE__)
30
+ require File.expand_path("../aptly/repo", __FILE__)
31
+ require File.expand_path("../aptly/package", __FILE__)
32
+ require File.expand_path("../aptly/repo_publish", __FILE__)
33
+
@@ -0,0 +1,194 @@
1
+ require 'puma'
2
+ require 'rack-flash'
3
+ require 'sinatra'
4
+ require 'sinatra/form_helpers'
5
+ require 'sinatra/partial'
6
+ require 'logger'
7
+
8
+ module Vx
9
+ module Aptly
10
+ class App < ::Sinatra::Base
11
+
12
+ register Sinatra::Partial
13
+
14
+ enable :logging, :dump_errors, :raise_errors, :sessions
15
+
16
+ set :partial_template_engine, :erb
17
+ set :server, :puma
18
+ set :static, true
19
+ set :public_dir, File.expand_path('../public', __FILE__)
20
+ set :views, File.expand_path('../views', __FILE__)
21
+
22
+ helpers Sinatra::FormHelpers
23
+
24
+ use Rack::CommonLogger, Aptly.logger
25
+ use Rack::MethodOverride
26
+ use Rack::Flash
27
+
28
+ if ENV['RACK_BASIC_AUTH'].to_s != ""
29
+ BASIC_AUTH_USER, _ = ENV['RACK_BASIC_AUTH'].split(":")
30
+ use Rack::Auth::Basic, "Restricted Area" do |username, password|
31
+ username == BASIC_AUTH_USER
32
+ end
33
+ end
34
+
35
+ helpers do
36
+
37
+ def ico name
38
+ %{<span class="fui-#{name}"></span>}
39
+ end
40
+
41
+ def number_to_human_size(size, precision=1)
42
+ size = Kernel.Float(size)
43
+ case
44
+ when size.to_i == 1; "1 Byte"
45
+ when size < 1024; "%d Bytes" % size
46
+ when size < (1024 * 1024); "%.#{precision}f KB" % (size / 1024.0)
47
+ when size < (1024 * 1024 * 1024); "%.#{precision}f MB" % (size / (1024 * 1024).to_f)
48
+ when size < (1024 * 1024 * 1024 * 1024); "%.#{precision}f GB" % (size / (1024 * 1024 * 1024).to_f)
49
+ else "%.#{precision}f TB" % (size / (1024 * 1024 * 1024 * 1024).to_f)
50
+ end.sub(/([0-9])\.?0+ /, '\1 ' )
51
+ end
52
+ end
53
+
54
+ ## Dashboard
55
+
56
+ get '/' do
57
+ @repos = Repo.all
58
+ @pubs = RepoPublish.all
59
+ erb :'/index', layout: :layout
60
+ end
61
+
62
+ ## Repos
63
+
64
+ get '/repos/new' do
65
+ @repo = Repo.new
66
+ erb :'/repos/new', layout: :layout
67
+ end
68
+
69
+ get '/repos/:name' do |name|
70
+ @repo = Repo.find name
71
+ erb :'/repos/show', layout: :layout
72
+ end
73
+
74
+ get '/repos/:name/edit' do |name|
75
+ @repo = Repo.find name
76
+ erb :'/repos/edit', layout: :layout
77
+ end
78
+
79
+ post '/repos' do
80
+ @repo = Repo.new params[:repo]
81
+ if @repo.create
82
+ flash[:notice] = @repo.notice
83
+ redirect to("/repos/#{@repo.name}")
84
+ else
85
+ erb :'/repos/new', layout: :layout
86
+ end
87
+ end
88
+
89
+ patch '/repos/:name' do |name|
90
+ @repo = Repo.new params[:repo]
91
+ if @repo.update
92
+ flash[:notice] = @repo.notice
93
+ redirect to("/repos/#{@repo.name}")
94
+ else
95
+ erb :'/repos/edit', layout: :layout
96
+ end
97
+ end
98
+
99
+ delete '/repos/:name' do |name|
100
+ @repo = Repo.find name
101
+ @repo.destroy
102
+ flash[:notice] = @repo.notice
103
+ redirect to('/')
104
+ end
105
+
106
+ ## Packages
107
+
108
+ get '/repos/:name/packages' do |name|
109
+ @repo = Repo.find name
110
+ erb :'repos/packages', layout: false
111
+ end
112
+
113
+ post '/repos/:name/packages' do |name|
114
+ repo = Repo.find name
115
+ path = params[:file][:tempfile].path
116
+ fname = params[:file][:filename]
117
+ package = Package.add repo, fname, path
118
+ if package.valid?
119
+ flash[:notice] = package.notice
120
+ else
121
+ flash[:error] = package.error.to_s
122
+ end
123
+ redirect to("/repos/#{repo.name}")
124
+ end
125
+
126
+ post '/repos/:name/push' do |name|
127
+ repo = Repo.find name
128
+ file_path = params[:file][:tempfile].path
129
+ content_type 'text/event-stream'
130
+ stream(:keep_open) do |out|
131
+ Package.push repo, file_path do |re|
132
+ out << re
133
+ end
134
+ end
135
+ end
136
+
137
+ delete '/repos/:name/packages/:id' do |name, id|
138
+ @repo = Repo.find name
139
+ @package = Package.find id
140
+ @package.destroy(@repo)
141
+ flash[:notice] = @package.notice
142
+ redirect to("/repos/#{@repo.name}")
143
+ end
144
+
145
+ ## Repo Publishes
146
+
147
+ get '/repo/publishes/new' do
148
+ @pub = RepoPublish.new
149
+ erb :'repo_publishes/new', layout: :layout
150
+ end
151
+
152
+ post '/repo/publishes' do
153
+ @pub = RepoPublish.new params[:pub]
154
+ @pub.create
155
+ if @pub.valid?
156
+ flash[:notice] = @pub.notice
157
+ redirect to("/")
158
+ else
159
+ erb :'repo_publishes/new', layout: :layout
160
+ end
161
+ end
162
+
163
+ patch '/repo/publishes/*' do |id|
164
+ @pub = RepoPublish.find(id)
165
+ @pub.update
166
+ flash[:notice] = @pub.notice
167
+ redirect to("/")
168
+ end
169
+
170
+ delete '/repo/publishes/*' do |id|
171
+ @pub = RepoPublish.find(id)
172
+ @pub.destroy
173
+ flash[:notice] = @pub.notice
174
+ redirect to("/")
175
+ end
176
+
177
+ # default route
178
+
179
+ get '/*' do |file|
180
+ abs_path = "#{ENV['HOME']}/.aptly/public/#{file}"
181
+ if File.readable?(abs_path)
182
+ send_file abs_path
183
+ else
184
+ status 404
185
+ end
186
+ end
187
+
188
+ error 404 do
189
+ File.read( File.expand_path('../public/404.html', __FILE__))
190
+ end
191
+
192
+ end
193
+ end
194
+ end