21 |
22 |
23 |
33 |
34 |
35 |
51 |
--------------------------------------------------------------------------------
/cmd/sampleapp/src/main.js:
--------------------------------------------------------------------------------
1 | // The Vue build version to load with the `import` command
2 | // (runtime-only or standalone) has been set in webpack.base.conf with an alias.
3 | import Vue from 'vue'
4 | import App from './App'
5 | import router from './router'
6 |
7 | Vue.config.productionTip = false
8 |
9 | /* eslint-disable no-new */
10 | new Vue({
11 | el: '#app',
12 | router,
13 | template: '',
14 | components: { App }
15 | })
16 |
--------------------------------------------------------------------------------
/cmd/sampleapp/src/router/index.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import Router from 'vue-router'
3 | import HelloWorld from '@/components/HelloWorld'
4 |
5 | Vue.use(Router)
6 |
7 | export default new Router({
8 | mode: 'history',
9 | routes: [
10 | {
11 | path: '/',
12 | name: 'HelloWorld',
13 | component: HelloWorld
14 | }
15 | ]
16 | })
17 |
--------------------------------------------------------------------------------
/cmd/sampleapp/static/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iheanyi/go-vue-statik/73f2089c4f2e7b60a4b54d70c1220c66e0d34012/cmd/sampleapp/static/.gitkeep
--------------------------------------------------------------------------------
/cmd/sampleapp/test/unit/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "env": {
3 | "jest": true
4 | },
5 | "globals": {
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/cmd/sampleapp/test/unit/jest.conf.js:
--------------------------------------------------------------------------------
1 | const path = require('path')
2 |
3 | module.exports = {
4 | rootDir: path.resolve(__dirname, '../../'),
5 | moduleFileExtensions: [
6 | 'js',
7 | 'json',
8 | 'vue'
9 | ],
10 | moduleNameMapper: {
11 | '^@/(.*)$': '/src/$1'
12 | },
13 | transform: {
14 | '^.+\\.js$': '/node_modules/babel-jest',
15 | '.*\\.(vue)$': '/node_modules/vue-jest'
16 | },
17 | snapshotSerializers: ['/node_modules/jest-serializer-vue'],
18 | setupFiles: ['/test/unit/setup'],
19 | mapCoverage: true,
20 | coverageDirectory: '/test/unit/coverage',
21 | collectCoverageFrom: [
22 | 'src/**/*.{js,vue}',
23 | '!src/main.js',
24 | '!src/router/index.js',
25 | '!**/node_modules/**'
26 | ]
27 | }
28 |
--------------------------------------------------------------------------------
/cmd/sampleapp/test/unit/setup.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 |
3 | Vue.config.productionTip = false
4 |
--------------------------------------------------------------------------------
/cmd/sampleapp/test/unit/specs/HelloWorld.spec.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import HelloWorld from '@/components/HelloWorld'
3 |
4 | describe('HelloWorld.vue', () => {
5 | it('should render correct contents', () => {
6 | const Constructor = Vue.extend(HelloWorld)
7 | const vm = new Constructor().$mount()
8 | expect(vm.$el.querySelector('.hello h1').textContent)
9 | .toEqual('Welcome to Your Vue.js App')
10 | })
11 | })
12 |
--------------------------------------------------------------------------------
/vendor/github.com/rakyll/statik/.travis.yml:
--------------------------------------------------------------------------------
1 | language: go
2 |
3 | go:
4 | - 1.7
5 | - 1.8
6 | - tip
7 |
8 | install:
9 | - go build -v
10 | - ./statik -src=./example/public -dest=./example/
11 |
--------------------------------------------------------------------------------
/vendor/github.com/rakyll/statik/LICENSE:
--------------------------------------------------------------------------------
1 |
2 | Apache License
3 | Version 2.0, January 2004
4 | http://www.apache.org/licenses/
5 |
6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
7 |
8 | 1. Definitions.
9 |
10 | "License" shall mean the terms and conditions for use, reproduction,
11 | and distribution as defined by Sections 1 through 9 of this document.
12 |
13 | "Licensor" shall mean the copyright owner or entity authorized by
14 | the copyright owner that is granting the License.
15 |
16 | "Legal Entity" shall mean the union of the acting entity and all
17 | other entities that control, are controlled by, or are under common
18 | control with that entity. For the purposes of this definition,
19 | "control" means (i) the power, direct or indirect, to cause the
20 | direction or management of such entity, whether by contract or
21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
22 | outstanding shares, or (iii) beneficial ownership of such entity.
23 |
24 | "You" (or "Your") shall mean an individual or Legal Entity
25 | exercising permissions granted by this License.
26 |
27 | "Source" form shall mean the preferred form for making modifications,
28 | including but not limited to software source code, documentation
29 | source, and configuration files.
30 |
31 | "Object" form shall mean any form resulting from mechanical
32 | transformation or translation of a Source form, including but
33 | not limited to compiled object code, generated documentation,
34 | and conversions to other media types.
35 |
36 | "Work" shall mean the work of authorship, whether in Source or
37 | Object form, made available under the License, as indicated by a
38 | copyright notice that is included in or attached to the work
39 | (an example is provided in the Appendix below).
40 |
41 | "Derivative Works" shall mean any work, whether in Source or Object
42 | form, that is based on (or derived from) the Work and for which the
43 | editorial revisions, annotations, elaborations, or other modifications
44 | represent, as a whole, an original work of authorship. For the purposes
45 | of this License, Derivative Works shall not include works that remain
46 | separable from, or merely link (or bind by name) to the interfaces of,
47 | the Work and Derivative Works thereof.
48 |
49 | "Contribution" shall mean any work of authorship, including
50 | the original version of the Work and any modifications or additions
51 | to that Work or Derivative Works thereof, that is intentionally
52 | submitted to Licensor for inclusion in the Work by the copyright owner
53 | or by an individual or Legal Entity authorized to submit on behalf of
54 | the copyright owner. For the purposes of this definition, "submitted"
55 | means any form of electronic, verbal, or written communication sent
56 | to the Licensor or its representatives, including but not limited to
57 | communication on electronic mailing lists, source code control systems,
58 | and issue tracking systems that are managed by, or on behalf of, the
59 | Licensor for the purpose of discussing and improving the Work, but
60 | excluding communication that is conspicuously marked or otherwise
61 | designated in writing by the copyright owner as "Not a Contribution."
62 |
63 | "Contributor" shall mean Licensor and any individual or Legal Entity
64 | on behalf of whom a Contribution has been received by Licensor and
65 | subsequently incorporated within the Work.
66 |
67 | 2. Grant of Copyright License. Subject to the terms and conditions of
68 | this License, each Contributor hereby grants to You a perpetual,
69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
70 | copyright license to reproduce, prepare Derivative Works of,
71 | publicly display, publicly perform, sublicense, and distribute the
72 | Work and such Derivative Works in Source or Object form.
73 |
74 | 3. Grant of Patent License. Subject to the terms and conditions of
75 | this License, each Contributor hereby grants to You a perpetual,
76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
77 | (except as stated in this section) patent license to make, have made,
78 | use, offer to sell, sell, import, and otherwise transfer the Work,
79 | where such license applies only to those patent claims licensable
80 | by such Contributor that are necessarily infringed by their
81 | Contribution(s) alone or by combination of their Contribution(s)
82 | with the Work to which such Contribution(s) was submitted. If You
83 | institute patent litigation against any entity (including a
84 | cross-claim or counterclaim in a lawsuit) alleging that the Work
85 | or a Contribution incorporated within the Work constitutes direct
86 | or contributory patent infringement, then any patent licenses
87 | granted to You under this License for that Work shall terminate
88 | as of the date such litigation is filed.
89 |
90 | 4. Redistribution. You may reproduce and distribute copies of the
91 | Work or Derivative Works thereof in any medium, with or without
92 | modifications, and in Source or Object form, provided that You
93 | meet the following conditions:
94 |
95 | (a) You must give any other recipients of the Work or
96 | Derivative Works a copy of this License; and
97 |
98 | (b) You must cause any modified files to carry prominent notices
99 | stating that You changed the files; and
100 |
101 | (c) You must retain, in the Source form of any Derivative Works
102 | that You distribute, all copyright, patent, trademark, and
103 | attribution notices from the Source form of the Work,
104 | excluding those notices that do not pertain to any part of
105 | the Derivative Works; and
106 |
107 | (d) If the Work includes a "NOTICE" text file as part of its
108 | distribution, then any Derivative Works that You distribute must
109 | include a readable copy of the attribution notices contained
110 | within such NOTICE file, excluding those notices that do not
111 | pertain to any part of the Derivative Works, in at least one
112 | of the following places: within a NOTICE text file distributed
113 | as part of the Derivative Works; within the Source form or
114 | documentation, if provided along with the Derivative Works; or,
115 | within a display generated by the Derivative Works, if and
116 | wherever such third-party notices normally appear. The contents
117 | of the NOTICE file are for informational purposes only and
118 | do not modify the License. You may add Your own attribution
119 | notices within Derivative Works that You distribute, alongside
120 | or as an addendum to the NOTICE text from the Work, provided
121 | that such additional attribution notices cannot be construed
122 | as modifying the License.
123 |
124 | You may add Your own copyright statement to Your modifications and
125 | may provide additional or different license terms and conditions
126 | for use, reproduction, or distribution of Your modifications, or
127 | for any such Derivative Works as a whole, provided Your use,
128 | reproduction, and distribution of the Work otherwise complies with
129 | the conditions stated in this License.
130 |
131 | 5. Submission of Contributions. Unless You explicitly state otherwise,
132 | any Contribution intentionally submitted for inclusion in the Work
133 | by You to the Licensor shall be under the terms and conditions of
134 | this License, without any additional terms or conditions.
135 | Notwithstanding the above, nothing herein shall supersede or modify
136 | the terms of any separate license agreement you may have executed
137 | with Licensor regarding such Contributions.
138 |
139 | 6. Trademarks. This License does not grant permission to use the trade
140 | names, trademarks, service marks, or product names of the Licensor,
141 | except as required for reasonable and customary use in describing the
142 | origin of the Work and reproducing the content of the NOTICE file.
143 |
144 | 7. Disclaimer of Warranty. Unless required by applicable law or
145 | agreed to in writing, Licensor provides the Work (and each
146 | Contributor provides its Contributions) on an "AS IS" BASIS,
147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
148 | implied, including, without limitation, any warranties or conditions
149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
150 | PARTICULAR PURPOSE. You are solely responsible for determining the
151 | appropriateness of using or redistributing the Work and assume any
152 | risks associated with Your exercise of permissions under this License.
153 |
154 | 8. Limitation of Liability. In no event and under no legal theory,
155 | whether in tort (including negligence), contract, or otherwise,
156 | unless required by applicable law (such as deliberate and grossly
157 | negligent acts) or agreed to in writing, shall any Contributor be
158 | liable to You for damages, including any direct, indirect, special,
159 | incidental, or consequential damages of any character arising as a
160 | result of this License or out of the use or inability to use the
161 | Work (including but not limited to damages for loss of goodwill,
162 | work stoppage, computer failure or malfunction, or any and all
163 | other commercial damages or losses), even if such Contributor
164 | has been advised of the possibility of such damages.
165 |
166 | 9. Accepting Warranty or Additional Liability. While redistributing
167 | the Work or Derivative Works thereof, You may choose to offer,
168 | and charge a fee for, acceptance of support, warranty, indemnity,
169 | or other liability obligations and/or rights consistent with this
170 | License. However, in accepting such obligations, You may act only
171 | on Your own behalf and on Your sole responsibility, not on behalf
172 | of any other Contributor, and only if You agree to indemnify,
173 | defend, and hold each Contributor harmless for any liability
174 | incurred by, or claims asserted against, such Contributor by reason
175 | of your accepting any such warranty or additional liability.
176 |
177 | END OF TERMS AND CONDITIONS
178 |
179 | APPENDIX: How to apply the Apache License to your work.
180 |
181 | To apply the Apache License to your work, attach the following
182 | boilerplate notice, with the fields enclosed by brackets "[]"
183 | replaced with your own identifying information. (Don't include
184 | the brackets!) The text should be enclosed in the appropriate
185 | comment syntax for the file format. We also recommend that a
186 | file or class name and description of purpose be included on the
187 | same "printed page" as the copyright notice for easier
188 | identification within third-party archives.
189 |
190 | Copyright 2014 Google Inc.
191 |
192 | Licensed under the Apache License, Version 2.0 (the "License");
193 | you may not use this file except in compliance with the License.
194 | You may obtain a copy of the License at
195 |
196 | http://www.apache.org/licenses/LICENSE-2.0
197 |
198 | Unless required by applicable law or agreed to in writing, software
199 | distributed under the License is distributed on an "AS IS" BASIS,
200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
201 | See the License for the specific language governing permissions and
202 | limitations under the License.
203 |
--------------------------------------------------------------------------------
/vendor/github.com/rakyll/statik/README.md:
--------------------------------------------------------------------------------
1 | # statik
2 |
3 | [](https://travis-ci.org/rakyll/statik)
4 |
5 | statik allows you to embed a directory of static files into your Go binary to be later served from an http.FileSystem.
6 |
7 | Is this a crazy idea? No, not necessarily. If you're building a tool that has a Web component, you typically want to serve some images, CSS and JavaScript. You like the comfort of distributing a single binary, so you don't want to mess with deploying them elsewhere. If your static files are not large in size and will be browsed by a few people, statik is a solution you are looking for.
8 |
9 | ## Usage
10 |
11 | Install the command line tool first.
12 |
13 | go get github.com/rakyll/statik
14 |
15 | statik is a tiny program that reads a directory and generates a source file contains its contents. The generated source file registers the directory contents to be used by statik file system.
16 |
17 | The command below will walk on the public path and generate a package called `statik` under the current working directory.
18 |
19 | $ statik -src=/path/to/your/project/public
20 |
21 | In your program, all your need to do is to import the generated package, initialize a new statik file system and serve.
22 |
23 | ~~~ go
24 | import (
25 | "github.com/rakyll/statik/fs"
26 |
27 | _ "./statik" // TODO: Replace with the absolute import path
28 | )
29 |
30 | // ...
31 |
32 | statikFS, _ := fs.New()
33 | http.ListenAndServe(":8080", http.FileServer(statikFS))
34 | ~~~
35 |
36 | Visit http://localhost:8080/path/to/file to see your file.
37 |
38 | There is also a working example under [example](https://github.com/rakyll/statik/tree/master/example) directory, follow the instructions to build and run it.
39 |
40 | Note: The idea and the implementation are hijacked from [camlistore](http://camlistore.org/). I decided to decouple it from its codebase due to the fact I'm actively in need of a similar solution for many of my projects. 
41 |
--------------------------------------------------------------------------------
/vendor/github.com/rakyll/statik/example/README.md:
--------------------------------------------------------------------------------
1 | # How to run?
2 |
3 | Run `go generate` to create a statik package that embeds the binary data underneath the public directory.
4 |
5 | $ go generate
6 |
7 | Once the statik package is generated, run the web server:
8 |
9 | $ go run main.go
10 |
11 | Visit [http://localhost:8080/public/hello.txt](http://localhost:8080/public/hello.txt) to see the file.
12 |
--------------------------------------------------------------------------------
/vendor/github.com/rakyll/statik/example/main.go:
--------------------------------------------------------------------------------
1 | //go:generate statik -src=./public
2 |
3 | package main
4 |
5 | import (
6 | "log"
7 | "net/http"
8 |
9 | _ "github.com/rakyll/statik/example/statik"
10 | "github.com/rakyll/statik/fs"
11 | )
12 |
13 | // Before buildling, run go generate.
14 | // Then, run the main program and visit http://localhost:8080/public/hello.txt
15 | func main() {
16 | statikFS, err := fs.New()
17 | if err != nil {
18 | log.Fatalf(err.Error())
19 | }
20 |
21 | http.Handle("/public/", http.StripPrefix("/public/", http.FileServer(statikFS)))
22 | http.ListenAndServe(":8080", nil)
23 | }
24 |
--------------------------------------------------------------------------------
/vendor/github.com/rakyll/statik/example/public/hello.txt:
--------------------------------------------------------------------------------
1 | Hello World
2 |
3 |
--------------------------------------------------------------------------------
/vendor/github.com/rakyll/statik/example/public/img/friends.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iheanyi/go-vue-statik/73f2089c4f2e7b60a4b54d70c1220c66e0d34012/vendor/github.com/rakyll/statik/example/public/img/friends.jpg
--------------------------------------------------------------------------------
/vendor/github.com/rakyll/statik/fs/fs.go:
--------------------------------------------------------------------------------
1 | // Copyright 2014 Google Inc. All Rights Reserved.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | // Package fs contains an HTTP file system that works with zip contents.
16 | package fs
17 |
18 | import (
19 | "archive/zip"
20 | "bytes"
21 | "errors"
22 | "fmt"
23 | "io/ioutil"
24 | "net/http"
25 | "os"
26 | "strings"
27 | )
28 |
29 | var zipData string
30 |
31 | // file holds unzipped read-only file contents and file metadata.
32 | type file struct {
33 | os.FileInfo
34 | data []byte
35 | }
36 |
37 | type statikFS struct {
38 | files map[string]file
39 | }
40 |
41 | // Register registers zip contents data, later used to initialize
42 | // the statik file system.
43 | func Register(data string) {
44 | zipData = data
45 | }
46 |
47 | // New creates a new file system with the registered zip contents data.
48 | // It unzips all files and stores them in an in-memory map.
49 | func New() (http.FileSystem, error) {
50 | if zipData == "" {
51 | return nil, errors.New("statik/fs: no zip data registered")
52 | }
53 | zipReader, err := zip.NewReader(strings.NewReader(zipData), int64(len(zipData)))
54 | if err != nil {
55 | return nil, err
56 | }
57 | files := make(map[string]file)
58 | for _, zipFile := range zipReader.File {
59 | unzipped, err := unzip(zipFile)
60 | if err != nil {
61 | return nil, fmt.Errorf("statik/fs: error unzipping file %q: %s", zipFile.Name, err)
62 | }
63 | files["/"+zipFile.Name] = file{
64 | FileInfo: zipFile.FileInfo(),
65 | data: unzipped,
66 | }
67 | }
68 | return &statikFS{files: files}, nil
69 | }
70 |
71 | func unzip(zf *zip.File) ([]byte, error) {
72 | rc, err := zf.Open()
73 | if err != nil {
74 | return nil, err
75 | }
76 | defer rc.Close()
77 | return ioutil.ReadAll(rc)
78 | }
79 |
80 | // Open returns a file matching the given file name, or os.ErrNotExists if
81 | // no file matching the given file name is found in the archive.
82 | // If a directory is requested, Open returns the file named "index.html"
83 | // in the requested directory, if that file exists.
84 | func (fs *statikFS) Open(name string) (http.File, error) {
85 | name = strings.Replace(name, "//", "/", -1)
86 | f, ok := fs.files[name]
87 | if ok {
88 | return newHTTPFile(f, false), nil
89 | }
90 | // The file doesn't match, but maybe it's a directory,
91 | // thus we should look for index.html
92 | indexName := strings.Replace(name+"/index.html", "//", "/", -1)
93 | f, ok = fs.files[indexName]
94 | if !ok {
95 | return nil, os.ErrNotExist
96 | }
97 | return newHTTPFile(f, true), nil
98 | }
99 |
100 | func newHTTPFile(file file, isDir bool) *httpFile {
101 | return &httpFile{
102 | file: file,
103 | reader: bytes.NewReader(file.data),
104 | isDir: isDir,
105 | }
106 | }
107 |
108 | // httpFile represents an HTTP file and acts as a bridge
109 | // between file and http.File.
110 | type httpFile struct {
111 | file
112 |
113 | reader *bytes.Reader
114 | isDir bool
115 | }
116 |
117 | // Read reads bytes into p, returns the number of read bytes.
118 | func (f *httpFile) Read(p []byte) (n int, err error) {
119 | return f.reader.Read(p)
120 | }
121 |
122 | // Seek seeks to the offset.
123 | func (f *httpFile) Seek(offset int64, whence int) (ret int64, err error) {
124 | return f.reader.Seek(offset, whence)
125 | }
126 |
127 | // Stat stats the file.
128 | func (f *httpFile) Stat() (os.FileInfo, error) {
129 | return f, nil
130 | }
131 |
132 | // IsDir returns true if the file location represents a directory.
133 | func (f *httpFile) IsDir() bool {
134 | return f.isDir
135 | }
136 |
137 | // Readdir returns an empty slice of files, directory
138 | // listing is disabled.
139 | func (f *httpFile) Readdir(count int) ([]os.FileInfo, error) {
140 | // directory listing is disabled.
141 | return make([]os.FileInfo, 0), nil
142 | }
143 |
144 | func (f *httpFile) Close() error {
145 | return nil
146 | }
147 |
--------------------------------------------------------------------------------
/vendor/github.com/rakyll/statik/statik.go:
--------------------------------------------------------------------------------
1 | // Copyright 2014 Google Inc. All Rights Reserved.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | // Package contains a program that generates code to register
16 | // a directory and its contents as zip data for statik file system.
17 | package main
18 |
19 | import (
20 | "archive/zip"
21 | "bytes"
22 | "flag"
23 | "fmt"
24 | "io"
25 | "io/ioutil"
26 | "os"
27 | "path"
28 | "path/filepath"
29 | "strings"
30 | "time"
31 | )
32 |
33 | const (
34 | namePackage = "statik"
35 | nameSourceFile = "statik.go"
36 | )
37 |
38 | var (
39 | flagSrc = flag.String("src", path.Join(".", "public"), "The path of the source directory.")
40 | flagDest = flag.String("dest", ".", "The destination path of the generated package.")
41 | flagNoMtime = flag.Bool("m", false, "Ignore modification times on files.")
42 | flagNoCompress = flag.Bool("Z", false, "Do not use compression to shrink the files.")
43 | flagForce = flag.Bool("f", false, "Overwrite destination file if it already exists.")
44 | )
45 |
46 | // mtimeDate holds the arbitrary mtime that we assign to files when
47 | // flagNoMtime is set.
48 | var mtimeDate = time.Date(2000, time.January, 1, 0, 0, 0, 0, time.UTC)
49 |
50 | func main() {
51 | flag.Parse()
52 |
53 | file, err := generateSource(*flagSrc)
54 | if err != nil {
55 | exitWithError(err)
56 | }
57 |
58 | destDir := path.Join(*flagDest, namePackage)
59 | err = os.MkdirAll(destDir, 0755)
60 | if err != nil {
61 | exitWithError(err)
62 | }
63 |
64 | err = rename(file.Name(), path.Join(destDir, nameSourceFile))
65 | if err != nil {
66 | exitWithError(err)
67 | }
68 | }
69 |
70 | // rename tries to os.Rename, but fall backs to copying from src
71 | // to dest and unlink the source if os.Rename fails.
72 | func rename(src, dest string) error {
73 | // Try to rename generated source.
74 | if err := os.Rename(src, dest); err == nil {
75 | return nil
76 | }
77 | // If the rename failed (might do so due to temporary file residing on a
78 | // different device), try to copy byte by byte.
79 | rc, err := os.Open(src)
80 | if err != nil {
81 | return err
82 | }
83 | defer func() {
84 | rc.Close()
85 | os.Remove(src) // ignore the error, source is in tmp.
86 | }()
87 |
88 | if _, err = os.Stat(dest); !os.IsNotExist(err) {
89 | if *flagForce {
90 | if err = os.Remove(dest); err != nil {
91 | return fmt.Errorf("file %q could not be deleted", dest)
92 | }
93 | } else {
94 | return fmt.Errorf("file %q already exists; use -f to overwrite", dest)
95 | }
96 | }
97 |
98 | wc, err := os.Create(dest)
99 | if err != nil {
100 | return err
101 | }
102 | defer wc.Close()
103 |
104 | if _, err = io.Copy(wc, rc); err != nil {
105 | // Delete remains of failed copy attempt.
106 | os.Remove(dest)
107 | }
108 | return err
109 | }
110 |
111 | // Walks on the source path and generates source code
112 | // that contains source directory's contents as zip contents.
113 | // Generates source registers generated zip contents data to
114 | // be read by the statik/fs HTTP file system.
115 | func generateSource(srcPath string) (file *os.File, err error) {
116 | var (
117 | buffer bytes.Buffer
118 | zipWriter io.Writer
119 | )
120 |
121 | zipWriter = &buffer
122 | f, err := ioutil.TempFile("", namePackage)
123 | if err != nil {
124 | return
125 | }
126 |
127 | zipWriter = io.MultiWriter(zipWriter, f)
128 | defer f.Close()
129 |
130 | w := zip.NewWriter(zipWriter)
131 | if err = filepath.Walk(srcPath, func(path string, fi os.FileInfo, err error) error {
132 | if err != nil {
133 | return err
134 | }
135 | // Ignore directories and hidden files.
136 | // No entry is needed for directories in a zip file.
137 | // Each file is represented with a path, no directory
138 | // entities are required to build the hierarchy.
139 | if fi.IsDir() || strings.HasPrefix(fi.Name(), ".") {
140 | return nil
141 | }
142 | relPath, err := filepath.Rel(srcPath, path)
143 | if err != nil {
144 | return err
145 | }
146 | b, err := ioutil.ReadFile(path)
147 | if err != nil {
148 | return err
149 | }
150 | fHeader, err := zip.FileInfoHeader(fi)
151 | if err != nil {
152 | return err
153 | }
154 | if *flagNoMtime {
155 | // Always use the same modification time so that
156 | // the output is deterministic with respect to the file contents.
157 | fHeader.SetModTime(mtimeDate)
158 | }
159 | fHeader.Name = filepath.ToSlash(relPath)
160 | if !*flagNoCompress {
161 | fHeader.Method = zip.Deflate
162 | }
163 | f, err := w.CreateHeader(fHeader)
164 | if err != nil {
165 | return err
166 | }
167 | _, err = f.Write(b)
168 | return err
169 | }); err != nil {
170 | return
171 | }
172 | if err = w.Close(); err != nil {
173 | return
174 | }
175 |
176 | // then embed it as a quoted string
177 | var qb bytes.Buffer
178 | fmt.Fprintf(&qb, `// Code generated by statik. DO NOT EDIT.
179 |
180 | package %s
181 |
182 | import (
183 | "github.com/rakyll/statik/fs"
184 | )
185 |
186 | func init() {
187 | data := "`, namePackage)
188 | FprintZipData(&qb, buffer.Bytes())
189 | fmt.Fprint(&qb, `"
190 | fs.Register(data)
191 | }
192 | `)
193 |
194 | if err = ioutil.WriteFile(f.Name(), qb.Bytes(), 0644); err != nil {
195 | return
196 | }
197 | return f, nil
198 | }
199 |
200 | // FprintZipData converts zip binary contents to a string literal.
201 | func FprintZipData(dest *bytes.Buffer, zipData []byte) {
202 | for _, b := range zipData {
203 | if b == '\n' {
204 | dest.WriteString(`\n`)
205 | continue
206 | }
207 | if b == '\\' {
208 | dest.WriteString(`\\`)
209 | continue
210 | }
211 | if b == '"' {
212 | dest.WriteString(`\"`)
213 | continue
214 | }
215 | if (b >= 32 && b <= 126) || b == '\t' {
216 | dest.WriteByte(b)
217 | continue
218 | }
219 | fmt.Fprintf(dest, "\\x%02x", b)
220 | }
221 | }
222 |
223 | // Prints out the error message and exists with a non-success signal.
224 | func exitWithError(err error) {
225 | fmt.Println(err)
226 | os.Exit(1)
227 | }
228 |
--------------------------------------------------------------------------------