| ... | ... |
@@ -5,17 +5,35 @@ go: |
| 5 | 5 |
- 1.2 |
| 6 | 6 |
- tip |
| 7 | 7 |
|
| 8 |
+env: |
|
| 9 |
+ - TEST_ASSETS=true |
|
| 10 |
+ - TEST_ASSETS=false |
|
| 11 |
+ |
|
| 12 |
+matrix: |
|
| 13 |
+ exclude: |
|
| 14 |
+ - go: 1.3 |
|
| 15 |
+ env: TEST_ASSETS=false |
|
| 16 |
+ - go: 1.2 |
|
| 17 |
+ env: TEST_ASSETS=true |
|
| 18 |
+ - go: tip |
|
| 19 |
+ env: TEST_ASSETS=true |
|
| 20 |
+ |
|
| 21 |
+before_install: |
|
| 22 |
+ - ./hack/before-install-assets.sh |
|
| 23 |
+ |
|
| 8 | 24 |
install: |
| 9 | 25 |
- ./hack/verify-gofmt.sh |
| 10 | 26 |
- ./hack/install-etcd.sh |
| 11 | 27 |
- ./hack/install-std-race.sh |
| 12 | 28 |
- go get code.google.com/p/go.tools/cmd/cover |
| 13 | 29 |
- ./hack/build-go.sh |
| 30 |
+ - ./hack/install-assets.sh |
|
| 14 | 31 |
|
| 15 | 32 |
script: |
| 16 | 33 |
- ./hack/test-go.sh |
| 17 | 34 |
- ./hack/test-cmd.sh |
| 18 | 35 |
- PATH=$HOME/gopath/bin:./third_party/etcd/bin:$PATH ./hack/test-integration.sh |
| 36 |
+ - ./hack/test-assets.sh |
|
| 19 | 37 |
|
| 20 | 38 |
notifications: |
| 21 | 39 |
irc: "chat.freenode.net#openshift-dev" |
| ... | ... |
@@ -363,6 +363,10 @@ |
| 363 | 363 |
"Rev": "8f74c29bc59d7f0b4fc6cfd6fa59f01532be9f9f" |
| 364 | 364 |
}, |
| 365 | 365 |
{
|
| 366 |
+ "ImportPath": "github.com/elazarl/go-bindata-assetfs", |
|
| 367 |
+ "Rev": "4e003f5e7162b67b84ea0f6117218f9c6f8fd2df" |
|
| 368 |
+ }, |
|
| 369 |
+ {
|
|
| 366 | 370 |
"ImportPath": "github.com/fsouza/go-dockerclient", |
| 367 | 371 |
"Comment": "0.2.1-241-g0dbb508", |
| 368 | 372 |
"Rev": "0dbb508e94dd899a6743d035d8f249c7634d26da" |
| ... | ... |
@@ -387,6 +391,11 @@ |
| 387 | 387 |
"Rev": "5a6d06c02600b1e57e55a9d9f71dbac1bfc9fe6c" |
| 388 | 388 |
}, |
| 389 | 389 |
{
|
| 390 |
+ "ImportPath": "github.com/jteeuwen/go-bindata", |
|
| 391 |
+ "Comment": "v3.0.5-31-g93b909d", |
|
| 392 |
+ "Rev": "93b909d1499a38620121b0a5eb43a18f3bccb083" |
|
| 393 |
+ }, |
|
| 394 |
+ {
|
|
| 390 | 395 |
"ImportPath": "github.com/google/gofuzz", |
| 391 | 396 |
"Rev": "aef70dacbc78771e35beb261bb3a72986adf7906" |
| 392 | 397 |
}, |
| 393 | 398 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,23 @@ |
| 0 |
+Copyright (c) 2014, Elazar Leibovich |
|
| 1 |
+All rights reserved. |
|
| 2 |
+ |
|
| 3 |
+Redistribution and use in source and binary forms, with or without |
|
| 4 |
+modification, are permitted provided that the following conditions are met: |
|
| 5 |
+ |
|
| 6 |
+* Redistributions of source code must retain the above copyright notice, this |
|
| 7 |
+ list of conditions and the following disclaimer. |
|
| 8 |
+ |
|
| 9 |
+* Redistributions in binary form must reproduce the above copyright notice, |
|
| 10 |
+ this list of conditions and the following disclaimer in the documentation |
|
| 11 |
+ and/or other materials provided with the distribution. |
|
| 12 |
+ |
|
| 13 |
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
|
| 14 |
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
|
| 15 |
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
|
| 16 |
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE |
|
| 17 |
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
|
| 18 |
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR |
|
| 19 |
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER |
|
| 20 |
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, |
|
| 21 |
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
|
| 22 |
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 0 | 23 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,18 @@ |
| 0 |
+go-bindata-http |
|
| 1 |
+=============== |
|
| 2 |
+ |
|
| 3 |
+Serve embedded files from [jteeuwen/go-bindata](https://github.com/jteeuwen/go-bindata) with `net/http`. |
|
| 4 |
+ |
|
| 5 |
+[GoDoc](http://godoc.org/github.com/elazarl/go-bindata-assetfs) |
|
| 6 |
+ |
|
| 7 |
+After running |
|
| 8 |
+ |
|
| 9 |
+ $ go-bindata data/... |
|
| 10 |
+ |
|
| 11 |
+Use |
|
| 12 |
+ |
|
| 13 |
+ http.Handle("/",
|
|
| 14 |
+ http.FileServer( |
|
| 15 |
+ &assetfs.AssetFS{Asset, AssetDir, "data"}))
|
|
| 16 |
+ |
|
| 17 |
+to serve files embedded from the `data` directory. |
| 0 | 18 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,141 @@ |
| 0 |
+package assetfs |
|
| 1 |
+ |
|
| 2 |
+import ( |
|
| 3 |
+ "bytes" |
|
| 4 |
+ "errors" |
|
| 5 |
+ "fmt" |
|
| 6 |
+ "io" |
|
| 7 |
+ "io/ioutil" |
|
| 8 |
+ "net/http" |
|
| 9 |
+ "os" |
|
| 10 |
+ "path" |
|
| 11 |
+ "path/filepath" |
|
| 12 |
+ "time" |
|
| 13 |
+) |
|
| 14 |
+ |
|
| 15 |
+// FakeFile implements os.FileInfo interface for a given path and size |
|
| 16 |
+type FakeFile struct {
|
|
| 17 |
+ // Path is the path of this file |
|
| 18 |
+ Path string |
|
| 19 |
+ // Dir marks of the path is a directory |
|
| 20 |
+ Dir bool |
|
| 21 |
+ // Len is the length of the fake file, zero if it is a directory |
|
| 22 |
+ Len int64 |
|
| 23 |
+} |
|
| 24 |
+ |
|
| 25 |
+func (f *FakeFile) Name() string {
|
|
| 26 |
+ _, name := filepath.Split(f.Path) |
|
| 27 |
+ return name |
|
| 28 |
+} |
|
| 29 |
+ |
|
| 30 |
+func (f *FakeFile) Mode() os.FileMode {
|
|
| 31 |
+ mode := os.FileMode(0644) |
|
| 32 |
+ if f.Dir {
|
|
| 33 |
+ return mode | os.ModeDir |
|
| 34 |
+ } |
|
| 35 |
+ return mode |
|
| 36 |
+} |
|
| 37 |
+ |
|
| 38 |
+func (f *FakeFile) ModTime() time.Time {
|
|
| 39 |
+ return time.Unix(0, 0) |
|
| 40 |
+} |
|
| 41 |
+ |
|
| 42 |
+func (f *FakeFile) Size() int64 {
|
|
| 43 |
+ return f.Len |
|
| 44 |
+} |
|
| 45 |
+ |
|
| 46 |
+func (f *FakeFile) IsDir() bool {
|
|
| 47 |
+ return f.Mode().IsDir() |
|
| 48 |
+} |
|
| 49 |
+ |
|
| 50 |
+func (f *FakeFile) Sys() interface{} {
|
|
| 51 |
+ return nil |
|
| 52 |
+} |
|
| 53 |
+ |
|
| 54 |
+// AssetFile implements http.File interface for a no-directory file with content |
|
| 55 |
+type AssetFile struct {
|
|
| 56 |
+ *bytes.Reader |
|
| 57 |
+ io.Closer |
|
| 58 |
+ FakeFile |
|
| 59 |
+} |
|
| 60 |
+ |
|
| 61 |
+func NewAssetFile(name string, content []byte) *AssetFile {
|
|
| 62 |
+ return &AssetFile{
|
|
| 63 |
+ bytes.NewReader(content), |
|
| 64 |
+ ioutil.NopCloser(nil), |
|
| 65 |
+ FakeFile{name, false, int64(len(content))}}
|
|
| 66 |
+} |
|
| 67 |
+ |
|
| 68 |
+func (f *AssetFile) Readdir(count int) ([]os.FileInfo, error) {
|
|
| 69 |
+ return nil, errors.New("not a directory")
|
|
| 70 |
+} |
|
| 71 |
+ |
|
| 72 |
+func (f *AssetFile) Stat() (os.FileInfo, error) {
|
|
| 73 |
+ return f, nil |
|
| 74 |
+} |
|
| 75 |
+ |
|
| 76 |
+// AssetDirectory implements http.File interface for a directory |
|
| 77 |
+type AssetDirectory struct {
|
|
| 78 |
+ AssetFile |
|
| 79 |
+ ChildrenRead int |
|
| 80 |
+ Children []os.FileInfo |
|
| 81 |
+} |
|
| 82 |
+ |
|
| 83 |
+func NewAssetDirectory(name string, children []string, fs *AssetFS) *AssetDirectory {
|
|
| 84 |
+ fileinfos := make([]os.FileInfo, 0, len(children)) |
|
| 85 |
+ for _, child := range children {
|
|
| 86 |
+ _, err := fs.AssetDir(filepath.Join(name, child)) |
|
| 87 |
+ fileinfos = append(fileinfos, &FakeFile{child, err == nil, 0})
|
|
| 88 |
+ } |
|
| 89 |
+ return &AssetDirectory{
|
|
| 90 |
+ AssetFile{
|
|
| 91 |
+ bytes.NewReader(nil), |
|
| 92 |
+ ioutil.NopCloser(nil), |
|
| 93 |
+ FakeFile{name, true, 0},
|
|
| 94 |
+ }, |
|
| 95 |
+ 0, |
|
| 96 |
+ fileinfos} |
|
| 97 |
+} |
|
| 98 |
+ |
|
| 99 |
+func (f *AssetDirectory) Readdir(count int) ([]os.FileInfo, error) {
|
|
| 100 |
+ fmt.Println(f, count) |
|
| 101 |
+ if count <= 0 {
|
|
| 102 |
+ return f.Children, nil |
|
| 103 |
+ } |
|
| 104 |
+ if f.ChildrenRead+count > len(f.Children) {
|
|
| 105 |
+ count = len(f.Children) - f.ChildrenRead |
|
| 106 |
+ } |
|
| 107 |
+ rv := f.Children[f.ChildrenRead : f.ChildrenRead+count] |
|
| 108 |
+ f.ChildrenRead += count |
|
| 109 |
+ return rv, nil |
|
| 110 |
+} |
|
| 111 |
+ |
|
| 112 |
+func (f *AssetDirectory) Stat() (os.FileInfo, error) {
|
|
| 113 |
+ return f, nil |
|
| 114 |
+} |
|
| 115 |
+ |
|
| 116 |
+// AssetFS implements http.FileSystem, allowing |
|
| 117 |
+// embedded files to be served from net/http package. |
|
| 118 |
+type AssetFS struct {
|
|
| 119 |
+ // Asset should return content of file in path if exists |
|
| 120 |
+ Asset func(path string) ([]byte, error) |
|
| 121 |
+ // AssetDir should return list of files in the path |
|
| 122 |
+ AssetDir func(path string) ([]string, error) |
|
| 123 |
+ // Prefix would be prepended to http requests |
|
| 124 |
+ Prefix string |
|
| 125 |
+} |
|
| 126 |
+ |
|
| 127 |
+func (fs *AssetFS) Open(name string) (http.File, error) {
|
|
| 128 |
+ name = path.Join(fs.Prefix, name) |
|
| 129 |
+ if len(name) > 0 && name[0] == '/' {
|
|
| 130 |
+ name = name[1:] |
|
| 131 |
+ } |
|
| 132 |
+ if children, err := fs.AssetDir(name); err == nil {
|
|
| 133 |
+ return NewAssetDirectory(name, children, fs), nil |
|
| 134 |
+ } |
|
| 135 |
+ b, err := fs.Asset(name) |
|
| 136 |
+ if err != nil {
|
|
| 137 |
+ return nil, err |
|
| 138 |
+ } |
|
| 139 |
+ return NewAssetFile(name, b), nil |
|
| 140 |
+} |
| 0 | 141 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,13 @@ |
| 0 |
+// assetfs allows packages to serve static content embedded |
|
| 1 |
+// with the go-bindata tool with the standard net/http package. |
|
| 2 |
+// |
|
| 3 |
+// See https://github.com/jteeuwen/go-bindata for more information |
|
| 4 |
+// about embedding binary data with go-bindata. |
|
| 5 |
+// |
|
| 6 |
+// Usage example, after running |
|
| 7 |
+// $ go-bindata data/... |
|
| 8 |
+// use: |
|
| 9 |
+// http.Handle("/",
|
|
| 10 |
+// http.FileServer( |
|
| 11 |
+// &assetfs.AssetFS{Asset, AssetDir, "data"}))
|
|
| 12 |
+package assetfs |
| 0 | 13 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,79 @@ |
| 0 |
+## Contribution guidelines. |
|
| 1 |
+ |
|
| 2 |
+So you wish to contribute to this project? Fantastic! |
|
| 3 |
+Here are a few guidelines to help you do this in a |
|
| 4 |
+streamlined fashion. |
|
| 5 |
+ |
|
| 6 |
+ |
|
| 7 |
+## Bug reports |
|
| 8 |
+ |
|
| 9 |
+When supplying a bug report, please consider the following guidelines. |
|
| 10 |
+These serve to make it easier for us to address the issue and find a solution. |
|
| 11 |
+Most of these are pretty self-evident, but sometimes it is still necessary |
|
| 12 |
+to reiterate them. |
|
| 13 |
+ |
|
| 14 |
+* Be clear in the way you express the problem. Use simple language and |
|
| 15 |
+ just enough of it to clearly define the issue. Not everyone is a native |
|
| 16 |
+ English speaker. And while most can handle themselves pretty well, |
|
| 17 |
+ it helps to stay away from more esoteric vocabulary. |
|
| 18 |
+ |
|
| 19 |
+ Be patient with non-native English speakers. If their bug reports |
|
| 20 |
+ or comments are hard to understand, just ask for clarification. |
|
| 21 |
+ Do not start guessing at their meaning, as this may just lead to |
|
| 22 |
+ more confusion and misunderstandings. |
|
| 23 |
+* Clearly define any information which is relevant to the problem. |
|
| 24 |
+ This includes library versions, operating system and any other |
|
| 25 |
+ external dependencies which may be needed. |
|
| 26 |
+* Where applicable, provide a step-by-step listing of the way to |
|
| 27 |
+ reproduce the problem. Make sure this is the simplest possible |
|
| 28 |
+ way to do so. Omit any and all unneccesary steps, because they may |
|
| 29 |
+ just complicate our understanding of the real problem. |
|
| 30 |
+ If need be, create a whole new code project on your local machine, |
|
| 31 |
+ which specifically tries to create the problem you are running into; |
|
| 32 |
+ nothing more, nothing less. |
|
| 33 |
+ |
|
| 34 |
+ Include this program in the bug report. It often suffices to paste |
|
| 35 |
+ the code in a [Gist](https://gist.github.com) or on the |
|
| 36 |
+ [Go playground](http://play.golang.org). |
|
| 37 |
+* If possible, provide us with a listing of the steps you have already |
|
| 38 |
+ undertaken to solve the problem. This can save us a great deal of |
|
| 39 |
+ wasted time, trying out solutions you have already covered. |
|
| 40 |
+ |
|
| 41 |
+ |
|
| 42 |
+## Pull requests |
|
| 43 |
+ |
|
| 44 |
+Bug reports are great. Supplying fixes to bugs is even better. |
|
| 45 |
+When submitting a pull request, the following guidelines are |
|
| 46 |
+good to keep in mind: |
|
| 47 |
+ |
|
| 48 |
+* `go fmt`: **Always** run your code through `go fmt`, before |
|
| 49 |
+ committing it. Code has to be readable by many different |
|
| 50 |
+ people. And the only way this will be as painless as possible, |
|
| 51 |
+ is if we all stick to the same code style. |
|
| 52 |
+ |
|
| 53 |
+ Some of our projects may have automated build-servers hooked up |
|
| 54 |
+ to commit hooks. These will vet any submitted code and determine |
|
| 55 |
+ if it meets a set of properties. One of which is code formatting. |
|
| 56 |
+ These servers will outright deny a submission which has not been |
|
| 57 |
+ run through `go fmt`, even if the code itself is correct. |
|
| 58 |
+ |
|
| 59 |
+ We try to maintain a zero-tolerance policy on this matter, |
|
| 60 |
+ because consistently formatted code makes life a great deal |
|
| 61 |
+ easier for everyone involved. |
|
| 62 |
+* Commit log messages: When committing changes, do so often and |
|
| 63 |
+ clearly -- Even if you have changed only 1 character in a code |
|
| 64 |
+ comment. This means that commit log messages should clearly state |
|
| 65 |
+ exactly what the change does and why. If it fixes a known issue, |
|
| 66 |
+ then mention the issue number in the commit log. E.g.: |
|
| 67 |
+ |
|
| 68 |
+ > Fixes return value for `foo/boo.Baz()` to be consistent with |
|
| 69 |
+ > the rest of the API. This addresses issue #32 |
|
| 70 |
+ |
|
| 71 |
+ Do not pile a lot of unrelated changes into a single commit. |
|
| 72 |
+ Pick and choose only those changes for a single commit, which are |
|
| 73 |
+ directly related. We would much rather see a hundred commits |
|
| 74 |
+ saying nothing but `"Runs go fmt"` in between any real fixes |
|
| 75 |
+ than have these style changes embedded in those real fixes. |
|
| 76 |
+ It creates a lot of noise when trying to review code. |
|
| 77 |
+ |
|
| 78 |
+ |
| 0 | 3 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,189 @@ |
| 0 |
+## bindata |
|
| 1 |
+ |
|
| 2 |
+This package converts any file into managable Go source code. Useful for |
|
| 3 |
+embedding binary data into a go program. The file data is optionally gzip |
|
| 4 |
+compressed before being converted to a raw byte slice. |
|
| 5 |
+ |
|
| 6 |
+It comes with a command line tool in the `go-bindata` sub directory. |
|
| 7 |
+This tool offers a set of command line options, used to customize the |
|
| 8 |
+output being generated. |
|
| 9 |
+ |
|
| 10 |
+ |
|
| 11 |
+### Installation |
|
| 12 |
+ |
|
| 13 |
+To install the library and command line program, use the following: |
|
| 14 |
+ |
|
| 15 |
+ go get github.com/jteeuwen/go-bindata/... |
|
| 16 |
+ |
|
| 17 |
+ |
|
| 18 |
+### Usage |
|
| 19 |
+ |
|
| 20 |
+Conversion is done on one or more sets of files. They are all embedded in a new |
|
| 21 |
+Go source file, along with a table of contents and an `Asset` function, |
|
| 22 |
+which allows quick access to the asset, based on its name. |
|
| 23 |
+ |
|
| 24 |
+The simplest invocation generates a `bindata.go` file in the current |
|
| 25 |
+working directory. It includes all assets from the `data` directory. |
|
| 26 |
+ |
|
| 27 |
+ $ go-bindata data/ |
|
| 28 |
+ |
|
| 29 |
+To include all input sub-directories recursively, use the elipsis postfix |
|
| 30 |
+as defined for Go import paths. Otherwise it will only consider assets in the |
|
| 31 |
+input directory itself. |
|
| 32 |
+ |
|
| 33 |
+ $ go-bindata data/... |
|
| 34 |
+ |
|
| 35 |
+To specify the name of the output file being generated, we use the following: |
|
| 36 |
+ |
|
| 37 |
+ $ go-bindata -o myfile.go data/ |
|
| 38 |
+ |
|
| 39 |
+Multiple input directories can be specified if necessary. |
|
| 40 |
+ |
|
| 41 |
+ $ go-bindata dir1/... /path/to/dir2/... dir3 |
|
| 42 |
+ |
|
| 43 |
+ |
|
| 44 |
+The following paragraphs detail some of the command line options which can be |
|
| 45 |
+supplied to `go-bindata`. Refer to the `testdata/out` directory for various |
|
| 46 |
+output examples from the assets in `testdata/in`. Each example uses different |
|
| 47 |
+command line options. |
|
| 48 |
+ |
|
| 49 |
+To ignore files, pass in regexes using -ignore, for example: |
|
| 50 |
+ |
|
| 51 |
+ $ go-bindata -ignore=\\.gitignore data/... |
|
| 52 |
+ |
|
| 53 |
+### Accessing an asset |
|
| 54 |
+ |
|
| 55 |
+To access asset data, we use the `Asset(string) []byte` function which |
|
| 56 |
+is included in the generated output. |
|
| 57 |
+ |
|
| 58 |
+ data := Asset("pub/style/foo.css")
|
|
| 59 |
+ if len(data) == 0 {
|
|
| 60 |
+ // Asset was not found. |
|
| 61 |
+ } |
|
| 62 |
+ |
|
| 63 |
+ // use asset data |
|
| 64 |
+ |
|
| 65 |
+ |
|
| 66 |
+### Debug vs Release builds |
|
| 67 |
+ |
|
| 68 |
+When invoking the program with the `-debug` flag, the generated code does |
|
| 69 |
+not actually include the asset data. Instead, it generates function stubs |
|
| 70 |
+which load the data from the original file on disk. The asset API remains |
|
| 71 |
+identical between debug and release builds, so your code will not have to |
|
| 72 |
+change. |
|
| 73 |
+ |
|
| 74 |
+This is useful during development when you expect the assets to change often. |
|
| 75 |
+The host application using these assets uses the same API in both cases and |
|
| 76 |
+will not have to care where the actual data comes from. |
|
| 77 |
+ |
|
| 78 |
+An example is a Go webserver with some embedded, static web content like |
|
| 79 |
+HTML, JS and CSS files. While developing it, you do not want to rebuild the |
|
| 80 |
+whole server and restart it every time you make a change to a bit of |
|
| 81 |
+javascript. You just want to build and launch the server once. Then just press |
|
| 82 |
+refresh in the browser to see those changes. Embedding the assets with the |
|
| 83 |
+`debug` flag allows you to do just that. When you are finished developing and |
|
| 84 |
+ready for deployment, just re-invoke `go-bindata` without the `-debug` flag. |
|
| 85 |
+It will now embed the latest version of the assets. |
|
| 86 |
+ |
|
| 87 |
+ |
|
| 88 |
+### Lower memory footprint |
|
| 89 |
+ |
|
| 90 |
+Using the `-nomemcopy` flag, will alter the way the output file is generated. |
|
| 91 |
+It will employ a hack that allows us to read the file data directly from |
|
| 92 |
+the compiled program's `.rodata` section. This ensures that when we call |
|
| 93 |
+call our generated function, we omit unnecessary memcopies. |
|
| 94 |
+ |
|
| 95 |
+The downside of this, is that it requires dependencies on the `reflect` and |
|
| 96 |
+`unsafe` packages. These may be restricted on platforms like AppEngine and |
|
| 97 |
+thus prevent you from using this mode. |
|
| 98 |
+ |
|
| 99 |
+Another disadvantage is that the byte slice we create, is strictly read-only. |
|
| 100 |
+For most use-cases this is not a problem, but if you ever try to alter the |
|
| 101 |
+returned byte slice, a runtime panic is thrown. Use this mode only on target |
|
| 102 |
+platforms where memory constraints are an issue. |
|
| 103 |
+ |
|
| 104 |
+The default behaviour is to use the old code generation method. This |
|
| 105 |
+prevents the two previously mentioned issues, but will employ at least one |
|
| 106 |
+extra memcopy and thus increase memory requirements. |
|
| 107 |
+ |
|
| 108 |
+For instance, consider the following two examples: |
|
| 109 |
+ |
|
| 110 |
+This would be the default mode, using an extra memcopy but gives a safe |
|
| 111 |
+implementation without dependencies on `reflect` and `unsafe`: |
|
| 112 |
+ |
|
| 113 |
+```go |
|
| 114 |
+func myfile() []byte {
|
|
| 115 |
+ return []byte{0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a}
|
|
| 116 |
+} |
|
| 117 |
+``` |
|
| 118 |
+ |
|
| 119 |
+Here is the same functionality, but uses the `.rodata` hack. |
|
| 120 |
+The byte slice returned from this example can not be written to without |
|
| 121 |
+generating a runtime error. |
|
| 122 |
+ |
|
| 123 |
+```go |
|
| 124 |
+var _myfile = "\x89\x50\x4e\x47\x0d\x0a\x1a" |
|
| 125 |
+ |
|
| 126 |
+func myfile() []byte {
|
|
| 127 |
+ var empty [0]byte |
|
| 128 |
+ sx := (*reflect.StringHeader)(unsafe.Pointer(&_myfile)) |
|
| 129 |
+ b := empty[:] |
|
| 130 |
+ bx := (*reflect.SliceHeader)(unsafe.Pointer(&b)) |
|
| 131 |
+ bx.Data = sx.Data |
|
| 132 |
+ bx.Len = len(_myfile) |
|
| 133 |
+ bx.Cap = bx.Len |
|
| 134 |
+ return b |
|
| 135 |
+} |
|
| 136 |
+``` |
|
| 137 |
+ |
|
| 138 |
+ |
|
| 139 |
+### Optional compression |
|
| 140 |
+ |
|
| 141 |
+When the `-nocompress` flag is given, the supplied resource is *not* GZIP |
|
| 142 |
+compressed before being turned into Go code. The data should still be accessed |
|
| 143 |
+through a function call, so nothing changes in the usage of the generated file. |
|
| 144 |
+ |
|
| 145 |
+This feature is useful if you do not care for compression, or the supplied |
|
| 146 |
+resource is already compressed. Doing it again would not add any value and may |
|
| 147 |
+even increase the size of the data. |
|
| 148 |
+ |
|
| 149 |
+The default behaviour of the program is to use compression. |
|
| 150 |
+ |
|
| 151 |
+ |
|
| 152 |
+### Path prefix stripping |
|
| 153 |
+ |
|
| 154 |
+The keys used in the `_bindata` map, are the same as the input file name |
|
| 155 |
+passed to `go-bindata`. This includes the path. In most cases, this is not |
|
| 156 |
+desireable, as it puts potentially sensitive information in your code base. |
|
| 157 |
+For this purpose, the tool supplies another command line flag `-prefix`. |
|
| 158 |
+This accepts a portion of a path name, which should be stripped off from |
|
| 159 |
+the map keys and function names. |
|
| 160 |
+ |
|
| 161 |
+For example, running without the `-prefix` flag, we get: |
|
| 162 |
+ |
|
| 163 |
+ $ go-bindata /path/to/templates/ |
|
| 164 |
+ |
|
| 165 |
+ _bindata["/path/to/templates/foo.html"] = path_to_templates_foo_html |
|
| 166 |
+ |
|
| 167 |
+Running with the `-prefix` flag, we get: |
|
| 168 |
+ |
|
| 169 |
+ $ go-bindata -prefix "/path/to/" /path/to/templates/ |
|
| 170 |
+ |
|
| 171 |
+ _bindata["templates/foo.html"] = templates_foo_html |
|
| 172 |
+ |
|
| 173 |
+ |
|
| 174 |
+### Build tags |
|
| 175 |
+ |
|
| 176 |
+With the optional `-tags` flag, you can specify any go build tags that |
|
| 177 |
+must be fulfilled for the output file to be included in a build. This |
|
| 178 |
+is useful when including binary data in multiple formats, where the desired |
|
| 179 |
+format is specified at build time with the appropriate tags. |
|
| 180 |
+ |
|
| 181 |
+The tags are appended to a `// +build` line in the beginning of the output file |
|
| 182 |
+and must follow the build tags syntax specified by the go tool. |
|
| 183 |
+ |
|
| 184 |
+### Related projects |
|
| 185 |
+ |
|
| 186 |
+[go-bindata-assetfs](https://github.com/elazarl/go-bindata-assetfs#readme) - |
|
| 187 |
+implements `http.FileSystem` interface. Allows you to serve assets with `net/http`. |
|
| 188 |
+ |
| 0 | 189 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,12 @@ |
| 0 |
+// This work is subject to the CC0 1.0 Universal (CC0 1.0) Public Domain Dedication |
|
| 1 |
+// license. Its contents can be found at: |
|
| 2 |
+// http://creativecommons.org/publicdomain/zero/1.0/ |
|
| 3 |
+ |
|
| 4 |
+package bindata |
|
| 5 |
+ |
|
| 6 |
+// Asset holds information about a single asset to be processed. |
|
| 7 |
+type Asset struct {
|
|
| 8 |
+ Path string // Full file path. |
|
| 9 |
+ Name string // Key used in TOC -- name by which asset is referenced. |
|
| 10 |
+ Func string // Function name for the procedure returning the asset contents. |
|
| 11 |
+} |
| 0 | 12 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,44 @@ |
| 0 |
+// This work is subject to the CC0 1.0 Universal (CC0 1.0) Public Domain Dedication |
|
| 1 |
+// license. Its contents can be found at: |
|
| 2 |
+// http://creativecommons.org/publicdomain/zero/1.0/ |
|
| 3 |
+ |
|
| 4 |
+package bindata |
|
| 5 |
+ |
|
| 6 |
+import ( |
|
| 7 |
+ "fmt" |
|
| 8 |
+ "io" |
|
| 9 |
+) |
|
| 10 |
+ |
|
| 11 |
+var ( |
|
| 12 |
+ newline = []byte{'\n'}
|
|
| 13 |
+ dataindent = []byte{'\t', '\t'}
|
|
| 14 |
+ space = []byte{' '}
|
|
| 15 |
+) |
|
| 16 |
+ |
|
| 17 |
+type ByteWriter struct {
|
|
| 18 |
+ io.Writer |
|
| 19 |
+ c int |
|
| 20 |
+} |
|
| 21 |
+ |
|
| 22 |
+func (w *ByteWriter) Write(p []byte) (n int, err error) {
|
|
| 23 |
+ if len(p) == 0 {
|
|
| 24 |
+ return |
|
| 25 |
+ } |
|
| 26 |
+ |
|
| 27 |
+ for n = range p {
|
|
| 28 |
+ if w.c%12 == 0 {
|
|
| 29 |
+ w.Writer.Write(newline) |
|
| 30 |
+ w.Writer.Write(dataindent) |
|
| 31 |
+ w.c = 0 |
|
| 32 |
+ } else {
|
|
| 33 |
+ w.Writer.Write(space) |
|
| 34 |
+ } |
|
| 35 |
+ |
|
| 36 |
+ fmt.Fprintf(w.Writer, "0x%02x,", p[n]) |
|
| 37 |
+ w.c++ |
|
| 38 |
+ } |
|
| 39 |
+ |
|
| 40 |
+ n++ |
|
| 41 |
+ |
|
| 42 |
+ return |
|
| 43 |
+} |
| 0 | 44 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,192 @@ |
| 0 |
+// This work is subject to the CC0 1.0 Universal (CC0 1.0) Public Domain Dedication |
|
| 1 |
+// license. Its contents can be found at: |
|
| 2 |
+// http://creativecommons.org/publicdomain/zero/1.0/ |
|
| 3 |
+ |
|
| 4 |
+package bindata |
|
| 5 |
+ |
|
| 6 |
+import ( |
|
| 7 |
+ "fmt" |
|
| 8 |
+ "os" |
|
| 9 |
+ "path/filepath" |
|
| 10 |
+ "regexp" |
|
| 11 |
+) |
|
| 12 |
+ |
|
| 13 |
+// InputConfig defines options on a asset directory to be convert. |
|
| 14 |
+type InputConfig struct {
|
|
| 15 |
+ // Path defines a directory containing asset files to be included |
|
| 16 |
+ // in the generated output. |
|
| 17 |
+ Path string |
|
| 18 |
+ |
|
| 19 |
+ // Recusive defines whether subdirectories of Path |
|
| 20 |
+ // should be recursively included in the conversion. |
|
| 21 |
+ Recursive bool |
|
| 22 |
+} |
|
| 23 |
+ |
|
| 24 |
+// Config defines a set of options for the asset conversion. |
|
| 25 |
+type Config struct {
|
|
| 26 |
+ // Name of the package to use. Defaults to 'main'. |
|
| 27 |
+ Package string |
|
| 28 |
+ |
|
| 29 |
+ // Tags specify a set of optional build tags, which should be |
|
| 30 |
+ // included in the generated output. The tags are appended to a |
|
| 31 |
+ // `// +build` line in the beginning of the output file |
|
| 32 |
+ // and must follow the build tags syntax specified by the go tool. |
|
| 33 |
+ Tags string |
|
| 34 |
+ |
|
| 35 |
+ // Input defines the directory path, containing all asset files as |
|
| 36 |
+ // well as whether to recursively process assets in any sub directories. |
|
| 37 |
+ Input []InputConfig |
|
| 38 |
+ |
|
| 39 |
+ // Output defines the output file for the generated code. |
|
| 40 |
+ // If left empty, this defaults to 'bindata.go' in the current |
|
| 41 |
+ // working directory. |
|
| 42 |
+ Output string |
|
| 43 |
+ |
|
| 44 |
+ // Prefix defines a path prefix which should be stripped from all |
|
| 45 |
+ // file names when generating the keys in the table of contents. |
|
| 46 |
+ // For example, running without the `-prefix` flag, we get: |
|
| 47 |
+ // |
|
| 48 |
+ // $ go-bindata /path/to/templates |
|
| 49 |
+ // go_bindata["/path/to/templates/foo.html"] = _path_to_templates_foo_html |
|
| 50 |
+ // |
|
| 51 |
+ // Running with the `-prefix` flag, we get: |
|
| 52 |
+ // |
|
| 53 |
+ // $ go-bindata -prefix "/path/to/" /path/to/templates/foo.html |
|
| 54 |
+ // go_bindata["templates/foo.html"] = templates_foo_html |
|
| 55 |
+ Prefix string |
|
| 56 |
+ |
|
| 57 |
+ // NoMemCopy will alter the way the output file is generated. |
|
| 58 |
+ // |
|
| 59 |
+ // It will employ a hack that allows us to read the file data directly from |
|
| 60 |
+ // the compiled program's `.rodata` section. This ensures that when we call |
|
| 61 |
+ // call our generated function, we omit unnecessary mem copies. |
|
| 62 |
+ // |
|
| 63 |
+ // The downside of this, is that it requires dependencies on the `reflect` and |
|
| 64 |
+ // `unsafe` packages. These may be restricted on platforms like AppEngine and |
|
| 65 |
+ // thus prevent you from using this mode. |
|
| 66 |
+ // |
|
| 67 |
+ // Another disadvantage is that the byte slice we create, is strictly read-only. |
|
| 68 |
+ // For most use-cases this is not a problem, but if you ever try to alter the |
|
| 69 |
+ // returned byte slice, a runtime panic is thrown. Use this mode only on target |
|
| 70 |
+ // platforms where memory constraints are an issue. |
|
| 71 |
+ // |
|
| 72 |
+ // The default behaviour is to use the old code generation method. This |
|
| 73 |
+ // prevents the two previously mentioned issues, but will employ at least one |
|
| 74 |
+ // extra memcopy and thus increase memory requirements. |
|
| 75 |
+ // |
|
| 76 |
+ // For instance, consider the following two examples: |
|
| 77 |
+ // |
|
| 78 |
+ // This would be the default mode, using an extra memcopy but gives a safe |
|
| 79 |
+ // implementation without dependencies on `reflect` and `unsafe`: |
|
| 80 |
+ // |
|
| 81 |
+ // func myfile() []byte {
|
|
| 82 |
+ // return []byte{0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a}
|
|
| 83 |
+ // } |
|
| 84 |
+ // |
|
| 85 |
+ // Here is the same functionality, but uses the `.rodata` hack. |
|
| 86 |
+ // The byte slice returned from this example can not be written to without |
|
| 87 |
+ // generating a runtime error. |
|
| 88 |
+ // |
|
| 89 |
+ // var _myfile = "\x89\x50\x4e\x47\x0d\x0a\x1a" |
|
| 90 |
+ // |
|
| 91 |
+ // func myfile() []byte {
|
|
| 92 |
+ // var empty [0]byte |
|
| 93 |
+ // sx := (*reflect.StringHeader)(unsafe.Pointer(&_myfile)) |
|
| 94 |
+ // b := empty[:] |
|
| 95 |
+ // bx := (*reflect.SliceHeader)(unsafe.Pointer(&b)) |
|
| 96 |
+ // bx.Data = sx.Data |
|
| 97 |
+ // bx.Len = len(_myfile) |
|
| 98 |
+ // bx.Cap = bx.Len |
|
| 99 |
+ // return b |
|
| 100 |
+ // } |
|
| 101 |
+ NoMemCopy bool |
|
| 102 |
+ |
|
| 103 |
+ // NoCompress means the assets are /not/ GZIP compressed before being turned |
|
| 104 |
+ // into Go code. The generated function will automatically unzip |
|
| 105 |
+ // the file data when called. Defaults to false. |
|
| 106 |
+ NoCompress bool |
|
| 107 |
+ |
|
| 108 |
+ // Perform a debug build. This generates an asset file, which |
|
| 109 |
+ // loads the asset contents directly from disk at their original |
|
| 110 |
+ // location, instead of embedding the contents in the code. |
|
| 111 |
+ // |
|
| 112 |
+ // This is mostly useful if you anticipate that the assets are |
|
| 113 |
+ // going to change during your development cycle. You will always |
|
| 114 |
+ // want your code to access the latest version of the asset. |
|
| 115 |
+ // Only in release mode, will the assets actually be embedded |
|
| 116 |
+ // in the code. The default behaviour is Release mode. |
|
| 117 |
+ Debug bool |
|
| 118 |
+ |
|
| 119 |
+ // Recursively process all assets in the input directory and its |
|
| 120 |
+ // sub directories. This defaults to false, so only files in the |
|
| 121 |
+ // input directory itself are read. |
|
| 122 |
+ Recursive bool |
|
| 123 |
+ |
|
| 124 |
+ // Ignores any filenames matching the regex pattern specified, e.g. |
|
| 125 |
+ // path/to/file.ext will ignore only that file, or \\.gitignore |
|
| 126 |
+ // will match any .gitignore file. |
|
| 127 |
+ // |
|
| 128 |
+ // This parameter can be provided multiple times. |
|
| 129 |
+ Ignore []*regexp.Regexp |
|
| 130 |
+} |
|
| 131 |
+ |
|
| 132 |
+// NewConfig returns a default configuration struct. |
|
| 133 |
+func NewConfig() *Config {
|
|
| 134 |
+ c := new(Config) |
|
| 135 |
+ c.Package = "main" |
|
| 136 |
+ c.NoMemCopy = false |
|
| 137 |
+ c.NoCompress = false |
|
| 138 |
+ c.Debug = false |
|
| 139 |
+ c.Recursive = false |
|
| 140 |
+ c.Output = "./bindata.go" |
|
| 141 |
+ c.Ignore = make([]*regexp.Regexp, 0) |
|
| 142 |
+ return c |
|
| 143 |
+} |
|
| 144 |
+ |
|
| 145 |
+// validate ensures the config has sane values. |
|
| 146 |
+// Part of which means checking if certain file/directory paths exist. |
|
| 147 |
+func (c *Config) validate() error {
|
|
| 148 |
+ if len(c.Package) == 0 {
|
|
| 149 |
+ return fmt.Errorf("Missing package name")
|
|
| 150 |
+ } |
|
| 151 |
+ |
|
| 152 |
+ for _, input := range c.Input {
|
|
| 153 |
+ _, err := os.Lstat(input.Path) |
|
| 154 |
+ if err != nil {
|
|
| 155 |
+ return fmt.Errorf("Failed to stat input path '%s': %v", input.Path, err)
|
|
| 156 |
+ } |
|
| 157 |
+ } |
|
| 158 |
+ |
|
| 159 |
+ if len(c.Output) == 0 {
|
|
| 160 |
+ cwd, err := os.Getwd() |
|
| 161 |
+ if err != nil {
|
|
| 162 |
+ return fmt.Errorf("Unable to determine current working directory.")
|
|
| 163 |
+ } |
|
| 164 |
+ |
|
| 165 |
+ c.Output = filepath.Join(cwd, "bindata.go") |
|
| 166 |
+ } |
|
| 167 |
+ |
|
| 168 |
+ stat, err := os.Lstat(c.Output) |
|
| 169 |
+ if err != nil {
|
|
| 170 |
+ if !os.IsNotExist(err) {
|
|
| 171 |
+ return fmt.Errorf("Output path: %v", err)
|
|
| 172 |
+ } |
|
| 173 |
+ |
|
| 174 |
+ // File does not exist. This is fine, just make |
|
| 175 |
+ // sure the directory it is to be in exists. |
|
| 176 |
+ dir, _ := filepath.Split(c.Output) |
|
| 177 |
+ if dir != "" {
|
|
| 178 |
+ err = os.MkdirAll(dir, 0744) |
|
| 179 |
+ |
|
| 180 |
+ if err != nil {
|
|
| 181 |
+ return fmt.Errorf("Create output directory: %v", err)
|
|
| 182 |
+ } |
|
| 183 |
+ } |
|
| 184 |
+ } |
|
| 185 |
+ |
|
| 186 |
+ if stat != nil && stat.IsDir() {
|
|
| 187 |
+ return fmt.Errorf("Output path is a directory.")
|
|
| 188 |
+ } |
|
| 189 |
+ |
|
| 190 |
+ return nil |
|
| 191 |
+} |
| 0 | 192 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,196 @@ |
| 0 |
+// This work is subject to the CC0 1.0 Universal (CC0 1.0) Public Domain Dedication |
|
| 1 |
+// license. Its contents can be found at: |
|
| 2 |
+// http://creativecommons.org/publicdomain/zero/1.0/ |
|
| 3 |
+ |
|
| 4 |
+package bindata |
|
| 5 |
+ |
|
| 6 |
+import ( |
|
| 7 |
+ "bufio" |
|
| 8 |
+ "fmt" |
|
| 9 |
+ "os" |
|
| 10 |
+ "path/filepath" |
|
| 11 |
+ "regexp" |
|
| 12 |
+ "strings" |
|
| 13 |
+ "unicode" |
|
| 14 |
+) |
|
| 15 |
+ |
|
| 16 |
+// Translate reads assets from an input directory, converts them |
|
| 17 |
+// to Go code and writes new files to the output specified |
|
| 18 |
+// in the given configuration. |
|
| 19 |
+func Translate(c *Config) error {
|
|
| 20 |
+ var toc []Asset |
|
| 21 |
+ |
|
| 22 |
+ // Ensure our configuration has sane values. |
|
| 23 |
+ err := c.validate() |
|
| 24 |
+ if err != nil {
|
|
| 25 |
+ return err |
|
| 26 |
+ } |
|
| 27 |
+ |
|
| 28 |
+ // Locate all the assets. |
|
| 29 |
+ for _, input := range c.Input {
|
|
| 30 |
+ err = findFiles(input.Path, c.Prefix, input.Recursive, &toc, c.Ignore) |
|
| 31 |
+ if err != nil {
|
|
| 32 |
+ return err |
|
| 33 |
+ } |
|
| 34 |
+ } |
|
| 35 |
+ |
|
| 36 |
+ // Create output file. |
|
| 37 |
+ fd, err := os.Create(c.Output) |
|
| 38 |
+ if err != nil {
|
|
| 39 |
+ return err |
|
| 40 |
+ } |
|
| 41 |
+ |
|
| 42 |
+ defer fd.Close() |
|
| 43 |
+ |
|
| 44 |
+ // Create a buffered writer for better performance. |
|
| 45 |
+ bfd := bufio.NewWriter(fd) |
|
| 46 |
+ defer bfd.Flush() |
|
| 47 |
+ |
|
| 48 |
+ // Write build tags, if applicable. |
|
| 49 |
+ if len(c.Tags) > 0 {
|
|
| 50 |
+ _, err = fmt.Fprintf(bfd, "// +build %s\n\n", c.Tags) |
|
| 51 |
+ if err != nil {
|
|
| 52 |
+ return err |
|
| 53 |
+ } |
|
| 54 |
+ } |
|
| 55 |
+ |
|
| 56 |
+ // Write package declaration. |
|
| 57 |
+ _, err = fmt.Fprintf(bfd, "package %s\n\n", c.Package) |
|
| 58 |
+ if err != nil {
|
|
| 59 |
+ return err |
|
| 60 |
+ } |
|
| 61 |
+ |
|
| 62 |
+ // Write assets. |
|
| 63 |
+ if c.Debug {
|
|
| 64 |
+ err = writeDebug(bfd, toc) |
|
| 65 |
+ } else {
|
|
| 66 |
+ err = writeRelease(bfd, c, toc) |
|
| 67 |
+ } |
|
| 68 |
+ |
|
| 69 |
+ if err != nil {
|
|
| 70 |
+ return err |
|
| 71 |
+ } |
|
| 72 |
+ |
|
| 73 |
+ // Write table of contents |
|
| 74 |
+ if err := writeTOC(bfd, toc); err != nil {
|
|
| 75 |
+ return err |
|
| 76 |
+ } |
|
| 77 |
+ // Write hierarchical tree of assets |
|
| 78 |
+ return writeTOCTree(bfd, toc) |
|
| 79 |
+} |
|
| 80 |
+ |
|
| 81 |
+// findFiles recursively finds all the file paths in the given directory tree. |
|
| 82 |
+// They are added to the given map as keys. Values will be safe function names |
|
| 83 |
+// for each file, which will be used when generating the output code. |
|
| 84 |
+func findFiles(dir, prefix string, recursive bool, toc *[]Asset, ignore []*regexp.Regexp) error {
|
|
| 85 |
+ if len(prefix) > 0 {
|
|
| 86 |
+ dir, _ = filepath.Abs(dir) |
|
| 87 |
+ prefix, _ = filepath.Abs(prefix) |
|
| 88 |
+ prefix = filepath.ToSlash(prefix) |
|
| 89 |
+ } |
|
| 90 |
+ |
|
| 91 |
+ fi, err := os.Stat(dir) |
|
| 92 |
+ if err != nil {
|
|
| 93 |
+ return err |
|
| 94 |
+ } |
|
| 95 |
+ |
|
| 96 |
+ var list []os.FileInfo |
|
| 97 |
+ |
|
| 98 |
+ if !fi.IsDir() {
|
|
| 99 |
+ dir = "" |
|
| 100 |
+ list = []os.FileInfo{fi}
|
|
| 101 |
+ } else {
|
|
| 102 |
+ fd, err := os.Open(dir) |
|
| 103 |
+ if err != nil {
|
|
| 104 |
+ return err |
|
| 105 |
+ } |
|
| 106 |
+ |
|
| 107 |
+ defer fd.Close() |
|
| 108 |
+ |
|
| 109 |
+ list, err = fd.Readdir(0) |
|
| 110 |
+ if err != nil {
|
|
| 111 |
+ return err |
|
| 112 |
+ } |
|
| 113 |
+ } |
|
| 114 |
+ |
|
| 115 |
+ knownFuncs := make(map[string]int) |
|
| 116 |
+ |
|
| 117 |
+ for _, file := range list {
|
|
| 118 |
+ var asset Asset |
|
| 119 |
+ asset.Path = filepath.Join(dir, file.Name()) |
|
| 120 |
+ asset.Name = filepath.ToSlash(asset.Path) |
|
| 121 |
+ |
|
| 122 |
+ ignoring := false |
|
| 123 |
+ for _, re := range ignore {
|
|
| 124 |
+ if re.MatchString(asset.Path) {
|
|
| 125 |
+ ignoring = true |
|
| 126 |
+ break |
|
| 127 |
+ } |
|
| 128 |
+ } |
|
| 129 |
+ if ignoring {
|
|
| 130 |
+ continue |
|
| 131 |
+ } |
|
| 132 |
+ |
|
| 133 |
+ if file.IsDir() {
|
|
| 134 |
+ if recursive {
|
|
| 135 |
+ findFiles(asset.Path, prefix, recursive, toc, ignore) |
|
| 136 |
+ } |
|
| 137 |
+ continue |
|
| 138 |
+ } |
|
| 139 |
+ |
|
| 140 |
+ if strings.HasPrefix(asset.Name, prefix) {
|
|
| 141 |
+ asset.Name = asset.Name[len(prefix):] |
|
| 142 |
+ } |
|
| 143 |
+ |
|
| 144 |
+ // If we have a leading slash, get rid of it. |
|
| 145 |
+ if len(asset.Name) > 0 && asset.Name[0] == '/' {
|
|
| 146 |
+ asset.Name = asset.Name[1:] |
|
| 147 |
+ } |
|
| 148 |
+ |
|
| 149 |
+ // This shouldn't happen. |
|
| 150 |
+ if len(asset.Name) == 0 {
|
|
| 151 |
+ return fmt.Errorf("Invalid file: %v", asset.Path)
|
|
| 152 |
+ } |
|
| 153 |
+ |
|
| 154 |
+ asset.Func = safeFunctionName(asset.Name, knownFuncs) |
|
| 155 |
+ asset.Path, _ = filepath.Abs(asset.Path) |
|
| 156 |
+ *toc = append(*toc, asset) |
|
| 157 |
+ } |
|
| 158 |
+ |
|
| 159 |
+ return nil |
|
| 160 |
+} |
|
| 161 |
+ |
|
| 162 |
+var regFuncName = regexp.MustCompile(`[^a-zA-Z0-9_]`) |
|
| 163 |
+ |
|
| 164 |
+// safeFunctionName converts the given name into a name |
|
| 165 |
+// which qualifies as a valid function identifier. It |
|
| 166 |
+// also compares against a known list of functions to |
|
| 167 |
+// prevent conflict based on name translation. |
|
| 168 |
+func safeFunctionName(name string, knownFuncs map[string]int) string {
|
|
| 169 |
+ name = strings.ToLower(name) |
|
| 170 |
+ name = regFuncName.ReplaceAllString(name, "_") |
|
| 171 |
+ |
|
| 172 |
+ // Get rid of "__" instances for niceness. |
|
| 173 |
+ for strings.Index(name, "__") > -1 {
|
|
| 174 |
+ name = strings.Replace(name, "__", "_", -1) |
|
| 175 |
+ } |
|
| 176 |
+ |
|
| 177 |
+ // Leading underscores are silly (unless they prefix a digit (see below)). |
|
| 178 |
+ for len(name) > 1 && name[0] == '_' {
|
|
| 179 |
+ name = name[1:] |
|
| 180 |
+ } |
|
| 181 |
+ |
|
| 182 |
+ // Identifier can't start with a digit. |
|
| 183 |
+ if unicode.IsDigit(rune(name[0])) {
|
|
| 184 |
+ name = "_" + name |
|
| 185 |
+ } |
|
| 186 |
+ |
|
| 187 |
+ if num, ok := knownFuncs[name]; ok {
|
|
| 188 |
+ knownFuncs[name] = num + 1 |
|
| 189 |
+ name = fmt.Sprintf("%s%d", name, num)
|
|
| 190 |
+ } else {
|
|
| 191 |
+ knownFuncs[name] = 2 |
|
| 192 |
+ } |
|
| 193 |
+ |
|
| 194 |
+ return name |
|
| 195 |
+} |
| 0 | 196 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,65 @@ |
| 0 |
+// This work is subject to the CC0 1.0 Universal (CC0 1.0) Public Domain Dedication |
|
| 1 |
+// license. Its contents can be found at: |
|
| 2 |
+// http://creativecommons.org/publicdomain/zero/1.0/ |
|
| 3 |
+ |
|
| 4 |
+package bindata |
|
| 5 |
+ |
|
| 6 |
+import ( |
|
| 7 |
+ "fmt" |
|
| 8 |
+ "io" |
|
| 9 |
+) |
|
| 10 |
+ |
|
| 11 |
+// writeDebug writes the debug code file. |
|
| 12 |
+func writeDebug(w io.Writer, toc []Asset) error {
|
|
| 13 |
+ err := writeDebugHeader(w) |
|
| 14 |
+ if err != nil {
|
|
| 15 |
+ return err |
|
| 16 |
+ } |
|
| 17 |
+ |
|
| 18 |
+ for i := range toc {
|
|
| 19 |
+ err = writeDebugAsset(w, &toc[i]) |
|
| 20 |
+ if err != nil {
|
|
| 21 |
+ return err |
|
| 22 |
+ } |
|
| 23 |
+ } |
|
| 24 |
+ |
|
| 25 |
+ return nil |
|
| 26 |
+} |
|
| 27 |
+ |
|
| 28 |
+// writeDebugHeader writes output file headers. |
|
| 29 |
+// This targets debug builds. |
|
| 30 |
+func writeDebugHeader(w io.Writer) error {
|
|
| 31 |
+ _, err := fmt.Fprintf(w, `import ( |
|
| 32 |
+ "fmt" |
|
| 33 |
+ "io/ioutil" |
|
| 34 |
+ "strings" |
|
| 35 |
+) |
|
| 36 |
+ |
|
| 37 |
+// bindata_read reads the given file from disk. It returns an error on failure. |
|
| 38 |
+func bindata_read(path, name string) ([]byte, error) {
|
|
| 39 |
+ buf, err := ioutil.ReadFile(path) |
|
| 40 |
+ if err != nil {
|
|
| 41 |
+ err = fmt.Errorf("Error reading asset %%s at %%s: %%v", name, path, err)
|
|
| 42 |
+ } |
|
| 43 |
+ return buf, err |
|
| 44 |
+} |
|
| 45 |
+ |
|
| 46 |
+`) |
|
| 47 |
+ return err |
|
| 48 |
+} |
|
| 49 |
+ |
|
| 50 |
+// writeDebugAsset write a debug entry for the given asset. |
|
| 51 |
+// A debug entry is simply a function which reads the asset from |
|
| 52 |
+// the original file (e.g.: from disk). |
|
| 53 |
+func writeDebugAsset(w io.Writer, asset *Asset) error {
|
|
| 54 |
+ _, err := fmt.Fprintf(w, `// %s reads file data from disk. It returns an error on failure. |
|
| 55 |
+func %s() ([]byte, error) {
|
|
| 56 |
+ return bindata_read( |
|
| 57 |
+ %q, |
|
| 58 |
+ %q, |
|
| 59 |
+ ) |
|
| 60 |
+} |
|
| 61 |
+ |
|
| 62 |
+`, asset.Func, asset.Func, asset.Path, asset.Name) |
|
| 63 |
+ return err |
|
| 64 |
+} |
| 0 | 65 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,129 @@ |
| 0 |
+// This work is subject to the CC0 1.0 Universal (CC0 1.0) Public Domain Dedication |
|
| 1 |
+// license. Its contents can be found at: |
|
| 2 |
+// http://creativecommons.org/publicdomain/zero/1.0/ |
|
| 3 |
+ |
|
| 4 |
+/* |
|
| 5 |
+bindata converts any file into managable Go source code. Useful for |
|
| 6 |
+embedding binary data into a go program. The file data is optionally gzip |
|
| 7 |
+compressed before being converted to a raw byte slice. |
|
| 8 |
+ |
|
| 9 |
+The following paragraphs cover some of the customization options |
|
| 10 |
+which can be specified in the Config struct, which must be passed into |
|
| 11 |
+the Translate() call. |
|
| 12 |
+ |
|
| 13 |
+ |
|
| 14 |
+Debug vs Release builds |
|
| 15 |
+ |
|
| 16 |
+When used with the `Debug` option, the generated code does not actually include |
|
| 17 |
+the asset data. Instead, it generates function stubs which load the data from |
|
| 18 |
+the original file on disk. The asset API remains identical between debug and |
|
| 19 |
+release builds, so your code will not have to change. |
|
| 20 |
+ |
|
| 21 |
+This is useful during development when you expect the assets to change often. |
|
| 22 |
+The host application using these assets uses the same API in both cases and |
|
| 23 |
+will not have to care where the actual data comes from. |
|
| 24 |
+ |
|
| 25 |
+An example is a Go webserver with some embedded, static web content like |
|
| 26 |
+HTML, JS and CSS files. While developing it, you do not want to rebuild the |
|
| 27 |
+whole server and restart it every time you make a change to a bit of |
|
| 28 |
+javascript. You just want to build and launch the server once. Then just press |
|
| 29 |
+refresh in the browser to see those changes. Embedding the assets with the |
|
| 30 |
+`debug` flag allows you to do just that. When you are finished developing and |
|
| 31 |
+ready for deployment, just re-invoke `go-bindata` without the `-debug` flag. |
|
| 32 |
+It will now embed the latest version of the assets. |
|
| 33 |
+ |
|
| 34 |
+ |
|
| 35 |
+Lower memory footprint |
|
| 36 |
+ |
|
| 37 |
+The `NoMemCopy` option will alter the way the output file is generated. |
|
| 38 |
+It will employ a hack that allows us to read the file data directly from |
|
| 39 |
+the compiled program's `.rodata` section. This ensures that when we call |
|
| 40 |
+call our generated function, we omit unnecessary memcopies. |
|
| 41 |
+ |
|
| 42 |
+The downside of this, is that it requires dependencies on the `reflect` and |
|
| 43 |
+`unsafe` packages. These may be restricted on platforms like AppEngine and |
|
| 44 |
+thus prevent you from using this mode. |
|
| 45 |
+ |
|
| 46 |
+Another disadvantage is that the byte slice we create, is strictly read-only. |
|
| 47 |
+For most use-cases this is not a problem, but if you ever try to alter the |
|
| 48 |
+returned byte slice, a runtime panic is thrown. Use this mode only on target |
|
| 49 |
+platforms where memory constraints are an issue. |
|
| 50 |
+ |
|
| 51 |
+The default behaviour is to use the old code generation method. This |
|
| 52 |
+prevents the two previously mentioned issues, but will employ at least one |
|
| 53 |
+extra memcopy and thus increase memory requirements. |
|
| 54 |
+ |
|
| 55 |
+For instance, consider the following two examples: |
|
| 56 |
+ |
|
| 57 |
+This would be the default mode, using an extra memcopy but gives a safe |
|
| 58 |
+implementation without dependencies on `reflect` and `unsafe`: |
|
| 59 |
+ |
|
| 60 |
+ func myfile() []byte {
|
|
| 61 |
+ return []byte{0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a}
|
|
| 62 |
+ } |
|
| 63 |
+ |
|
| 64 |
+Here is the same functionality, but uses the `.rodata` hack. |
|
| 65 |
+The byte slice returned from this example can not be written to without |
|
| 66 |
+generating a runtime error. |
|
| 67 |
+ |
|
| 68 |
+ var _myfile = "\x89\x50\x4e\x47\x0d\x0a\x1a" |
|
| 69 |
+ |
|
| 70 |
+ func myfile() []byte {
|
|
| 71 |
+ var empty [0]byte |
|
| 72 |
+ sx := (*reflect.StringHeader)(unsafe.Pointer(&_myfile)) |
|
| 73 |
+ b := empty[:] |
|
| 74 |
+ bx := (*reflect.SliceHeader)(unsafe.Pointer(&b)) |
|
| 75 |
+ bx.Data = sx.Data |
|
| 76 |
+ bx.Len = len(_myfile) |
|
| 77 |
+ bx.Cap = bx.Len |
|
| 78 |
+ return b |
|
| 79 |
+ } |
|
| 80 |
+ |
|
| 81 |
+ |
|
| 82 |
+Optional compression |
|
| 83 |
+ |
|
| 84 |
+The NoCompress option indicates that the supplied assets are *not* GZIP |
|
| 85 |
+compressed before being turned into Go code. The data should still be accessed |
|
| 86 |
+through a function call, so nothing changes in the API. |
|
| 87 |
+ |
|
| 88 |
+This feature is useful if you do not care for compression, or the supplied |
|
| 89 |
+resource is already compressed. Doing it again would not add any value and may |
|
| 90 |
+even increase the size of the data. |
|
| 91 |
+ |
|
| 92 |
+The default behaviour of the program is to use compression. |
|
| 93 |
+ |
|
| 94 |
+ |
|
| 95 |
+Path prefix stripping |
|
| 96 |
+ |
|
| 97 |
+The keys used in the `_bindata` map are the same as the input file name |
|
| 98 |
+passed to `go-bindata`. This includes the path. In most cases, this is not |
|
| 99 |
+desireable, as it puts potentially sensitive information in your code base. |
|
| 100 |
+For this purpose, the tool supplies another command line flag `-prefix`. |
|
| 101 |
+This accepts a portion of a path name, which should be stripped off from |
|
| 102 |
+the map keys and function names. |
|
| 103 |
+ |
|
| 104 |
+For example, running without the `-prefix` flag, we get: |
|
| 105 |
+ |
|
| 106 |
+ $ go-bindata /path/to/templates/ |
|
| 107 |
+ |
|
| 108 |
+ _bindata["/path/to/templates/foo.html"] = path_to_templates_foo_html |
|
| 109 |
+ |
|
| 110 |
+Running with the `-prefix` flag, we get: |
|
| 111 |
+ |
|
| 112 |
+ $ go-bindata -prefix "/path/to/" /path/to/templates/ |
|
| 113 |
+ |
|
| 114 |
+ _bindata["templates/foo.html"] = templates_foo_html |
|
| 115 |
+ |
|
| 116 |
+ |
|
| 117 |
+Build tags |
|
| 118 |
+ |
|
| 119 |
+With the optional Tags field, you can specify any go build tags that |
|
| 120 |
+must be fulfilled for the output file to be included in a build. This |
|
| 121 |
+is useful when including binary data in multiple formats, where the desired |
|
| 122 |
+format is specified at build time with the appropriate tags. |
|
| 123 |
+ |
|
| 124 |
+The tags are appended to a `// +build` line in the beginning of the output file |
|
| 125 |
+and must follow the build tags syntax specified by the go tool. |
|
| 126 |
+ |
|
| 127 |
+*/ |
|
| 128 |
+package bindata |
| 0 | 129 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,22 @@ |
| 0 |
+package main |
|
| 1 |
+ |
|
| 2 |
+import "strings" |
|
| 3 |
+ |
|
| 4 |
+// borrowed from https://github.com/hashicorp/serf/blob/master/command/agent/flag_slice_value.go |
|
| 5 |
+ |
|
| 6 |
+// AppendSliceValue implements the flag.Value interface and allows multiple |
|
| 7 |
+// calls to the same variable to append a list. |
|
| 8 |
+type AppendSliceValue []string |
|
| 9 |
+ |
|
| 10 |
+func (s *AppendSliceValue) String() string {
|
|
| 11 |
+ return strings.Join(*s, ",") |
|
| 12 |
+} |
|
| 13 |
+ |
|
| 14 |
+func (s *AppendSliceValue) Set(value string) error {
|
|
| 15 |
+ if *s == nil {
|
|
| 16 |
+ *s = make([]string, 0, 1) |
|
| 17 |
+ } |
|
| 18 |
+ |
|
| 19 |
+ *s = append(*s, value) |
|
| 20 |
+ return nil |
|
| 21 |
+} |
| 0 | 22 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,102 @@ |
| 0 |
+// This work is subject to the CC0 1.0 Universal (CC0 1.0) Public Domain Dedication |
|
| 1 |
+// license. Its contents can be found at: |
|
| 2 |
+// http://creativecommons.org/publicdomain/zero/1.0/ |
|
| 3 |
+ |
|
| 4 |
+package main |
|
| 5 |
+ |
|
| 6 |
+import ( |
|
| 7 |
+ "flag" |
|
| 8 |
+ "fmt" |
|
| 9 |
+ "github.com/jteeuwen/go-bindata" |
|
| 10 |
+ "os" |
|
| 11 |
+ "path/filepath" |
|
| 12 |
+ "regexp" |
|
| 13 |
+ "strings" |
|
| 14 |
+) |
|
| 15 |
+ |
|
| 16 |
+func main() {
|
|
| 17 |
+ cfg := parseArgs() |
|
| 18 |
+ err := bindata.Translate(cfg) |
|
| 19 |
+ |
|
| 20 |
+ if err != nil {
|
|
| 21 |
+ fmt.Fprintf(os.Stderr, "bindata: %v\n", err) |
|
| 22 |
+ os.Exit(1) |
|
| 23 |
+ } |
|
| 24 |
+} |
|
| 25 |
+ |
|
| 26 |
+// parseArgs create s a new, filled configuration instance |
|
| 27 |
+// by reading and parsing command line options. |
|
| 28 |
+// |
|
| 29 |
+// This function exits the program with an error, if |
|
| 30 |
+// any of the command line options are incorrect. |
|
| 31 |
+func parseArgs() *bindata.Config {
|
|
| 32 |
+ var version bool |
|
| 33 |
+ |
|
| 34 |
+ c := bindata.NewConfig() |
|
| 35 |
+ |
|
| 36 |
+ flag.Usage = func() {
|
|
| 37 |
+ fmt.Printf("Usage: %s [options] <input directories>\n\n", os.Args[0])
|
|
| 38 |
+ flag.PrintDefaults() |
|
| 39 |
+ } |
|
| 40 |
+ |
|
| 41 |
+ flag.BoolVar(&c.Debug, "debug", c.Debug, "Do not embed the assets, but provide the embedding API. Contents will still be loaded from disk.") |
|
| 42 |
+ flag.StringVar(&c.Tags, "tags", c.Tags, "Optional set of build tags to include.") |
|
| 43 |
+ flag.StringVar(&c.Prefix, "prefix", c.Prefix, "Optional path prefix to strip off asset names.") |
|
| 44 |
+ flag.StringVar(&c.Package, "pkg", c.Package, "Package name to use in the generated code.") |
|
| 45 |
+ flag.BoolVar(&c.NoMemCopy, "nomemcopy", c.NoMemCopy, "Use a .rodata hack to get rid of unnecessary memcopies. Refer to the documentation to see what implications this carries.") |
|
| 46 |
+ flag.BoolVar(&c.NoCompress, "nocompress", c.NoCompress, "Assets will *not* be GZIP compressed when this flag is specified.") |
|
| 47 |
+ flag.StringVar(&c.Output, "o", c.Output, "Optional name of the output file to be generated.") |
|
| 48 |
+ flag.BoolVar(&version, "version", false, "Displays version information.") |
|
| 49 |
+ |
|
| 50 |
+ ignore := make([]string, 0) |
|
| 51 |
+ flag.Var((*AppendSliceValue)(&ignore), "ignore", "Regex pattern to ignore") |
|
| 52 |
+ |
|
| 53 |
+ flag.Parse() |
|
| 54 |
+ |
|
| 55 |
+ patterns := make([]*regexp.Regexp, 0) |
|
| 56 |
+ for _, pattern := range ignore {
|
|
| 57 |
+ patterns = append(patterns, regexp.MustCompile(pattern)) |
|
| 58 |
+ } |
|
| 59 |
+ c.Ignore = patterns |
|
| 60 |
+ |
|
| 61 |
+ if version {
|
|
| 62 |
+ fmt.Printf("%s\n", Version())
|
|
| 63 |
+ os.Exit(0) |
|
| 64 |
+ } |
|
| 65 |
+ |
|
| 66 |
+ // Make sure we have input paths. |
|
| 67 |
+ if flag.NArg() == 0 {
|
|
| 68 |
+ fmt.Fprintf(os.Stderr, "Missing <input dir>\n\n") |
|
| 69 |
+ flag.Usage() |
|
| 70 |
+ os.Exit(1) |
|
| 71 |
+ } |
|
| 72 |
+ |
|
| 73 |
+ // Create input configurations. |
|
| 74 |
+ c.Input = make([]bindata.InputConfig, flag.NArg()) |
|
| 75 |
+ for i := range c.Input {
|
|
| 76 |
+ c.Input[i] = parseInput(flag.Arg(i)) |
|
| 77 |
+ } |
|
| 78 |
+ |
|
| 79 |
+ return c |
|
| 80 |
+} |
|
| 81 |
+ |
|
| 82 |
+// parseRecursive determines whether the given path has a recrusive indicator and |
|
| 83 |
+// returns a new path with the recursive indicator chopped off if it does. |
|
| 84 |
+// |
|
| 85 |
+// ex: |
|
| 86 |
+// /path/to/foo/... -> (/path/to/foo, true) |
|
| 87 |
+// /path/to/bar -> (/path/to/bar, false) |
|
| 88 |
+func parseInput(path string) bindata.InputConfig {
|
|
| 89 |
+ if strings.HasSuffix(path, "/...") {
|
|
| 90 |
+ return bindata.InputConfig{
|
|
| 91 |
+ Path: filepath.Clean(path[:len(path)-4]), |
|
| 92 |
+ Recursive: true, |
|
| 93 |
+ } |
|
| 94 |
+ } else {
|
|
| 95 |
+ return bindata.InputConfig{
|
|
| 96 |
+ Path: filepath.Clean(path), |
|
| 97 |
+ Recursive: false, |
|
| 98 |
+ } |
|
| 99 |
+ } |
|
| 100 |
+ |
|
| 101 |
+} |
| 0 | 102 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,31 @@ |
| 0 |
+// This work is subject to the CC0 1.0 Universal (CC0 1.0) Public Domain Dedication |
|
| 1 |
+// license. Its contents can be found at: |
|
| 2 |
+// http://creativecommons.org/publicdomain/zero/1.0/ |
|
| 3 |
+ |
|
| 4 |
+package main |
|
| 5 |
+ |
|
| 6 |
+import ( |
|
| 7 |
+ "fmt" |
|
| 8 |
+ "runtime" |
|
| 9 |
+) |
|
| 10 |
+ |
|
| 11 |
+const ( |
|
| 12 |
+ AppName = "go-bindata" |
|
| 13 |
+ AppVersionMajor = 3 |
|
| 14 |
+ AppVersionMinor = 1 |
|
| 15 |
+) |
|
| 16 |
+ |
|
| 17 |
+// revision part of the program version. |
|
| 18 |
+// This will be set automatically at build time like so: |
|
| 19 |
+// |
|
| 20 |
+// go build -ldflags "-X main.AppVersionRev `date -u +%s`" |
|
| 21 |
+var AppVersionRev string |
|
| 22 |
+ |
|
| 23 |
+func Version() string {
|
|
| 24 |
+ if len(AppVersionRev) == 0 {
|
|
| 25 |
+ AppVersionRev = "0" |
|
| 26 |
+ } |
|
| 27 |
+ |
|
| 28 |
+ return fmt.Sprintf("%s %d.%d.%s (Go runtime %s).\nCopyright (c) 2010-2013, Jim Teeuwen.",
|
|
| 29 |
+ AppName, AppVersionMajor, AppVersionMinor, AppVersionRev, runtime.Version()) |
|
| 30 |
+} |
| 0 | 31 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,272 @@ |
| 0 |
+// This work is subject to the CC0 1.0 Universal (CC0 1.0) Public Domain Dedication |
|
| 1 |
+// license. Its contents can be found at: |
|
| 2 |
+// http://creativecommons.org/publicdomain/zero/1.0/ |
|
| 3 |
+ |
|
| 4 |
+package bindata |
|
| 5 |
+ |
|
| 6 |
+import ( |
|
| 7 |
+ "compress/gzip" |
|
| 8 |
+ "fmt" |
|
| 9 |
+ "io" |
|
| 10 |
+ "os" |
|
| 11 |
+) |
|
| 12 |
+ |
|
| 13 |
+// writeRelease writes the release code file. |
|
| 14 |
+func writeRelease(w io.Writer, c *Config, toc []Asset) error {
|
|
| 15 |
+ err := writeReleaseHeader(w, c) |
|
| 16 |
+ if err != nil {
|
|
| 17 |
+ return err |
|
| 18 |
+ } |
|
| 19 |
+ |
|
| 20 |
+ for i := range toc {
|
|
| 21 |
+ err = writeReleaseAsset(w, c, &toc[i]) |
|
| 22 |
+ if err != nil {
|
|
| 23 |
+ return err |
|
| 24 |
+ } |
|
| 25 |
+ } |
|
| 26 |
+ |
|
| 27 |
+ return nil |
|
| 28 |
+} |
|
| 29 |
+ |
|
| 30 |
+// writeReleaseHeader writes output file headers. |
|
| 31 |
+// This targets release builds. |
|
| 32 |
+func writeReleaseHeader(w io.Writer, c *Config) error {
|
|
| 33 |
+ if c.NoCompress {
|
|
| 34 |
+ if c.NoMemCopy {
|
|
| 35 |
+ return header_uncompressed_nomemcopy(w) |
|
| 36 |
+ } else {
|
|
| 37 |
+ return header_uncompressed_memcopy(w) |
|
| 38 |
+ } |
|
| 39 |
+ } else {
|
|
| 40 |
+ if c.NoMemCopy {
|
|
| 41 |
+ return header_compressed_nomemcopy(w) |
|
| 42 |
+ } else {
|
|
| 43 |
+ return header_compressed_memcopy(w) |
|
| 44 |
+ } |
|
| 45 |
+ } |
|
| 46 |
+} |
|
| 47 |
+ |
|
| 48 |
+// writeReleaseAsset write a release entry for the given asset. |
|
| 49 |
+// A release entry is a function which embeds and returns |
|
| 50 |
+// the file's byte content. |
|
| 51 |
+func writeReleaseAsset(w io.Writer, c *Config, asset *Asset) error {
|
|
| 52 |
+ fd, err := os.Open(asset.Path) |
|
| 53 |
+ if err != nil {
|
|
| 54 |
+ return err |
|
| 55 |
+ } |
|
| 56 |
+ |
|
| 57 |
+ defer fd.Close() |
|
| 58 |
+ |
|
| 59 |
+ if c.NoCompress {
|
|
| 60 |
+ if c.NoMemCopy {
|
|
| 61 |
+ return uncompressed_nomemcopy(w, asset, fd) |
|
| 62 |
+ } else {
|
|
| 63 |
+ return uncompressed_memcopy(w, asset, fd) |
|
| 64 |
+ } |
|
| 65 |
+ } else {
|
|
| 66 |
+ if c.NoMemCopy {
|
|
| 67 |
+ return compressed_nomemcopy(w, asset, fd) |
|
| 68 |
+ } else {
|
|
| 69 |
+ return compressed_memcopy(w, asset, fd) |
|
| 70 |
+ } |
|
| 71 |
+ } |
|
| 72 |
+} |
|
| 73 |
+ |
|
| 74 |
+func header_compressed_nomemcopy(w io.Writer) error {
|
|
| 75 |
+ _, err := fmt.Fprintf(w, `import ( |
|
| 76 |
+ "bytes" |
|
| 77 |
+ "compress/gzip" |
|
| 78 |
+ "fmt" |
|
| 79 |
+ "io" |
|
| 80 |
+ "reflect" |
|
| 81 |
+ "strings" |
|
| 82 |
+ "unsafe" |
|
| 83 |
+) |
|
| 84 |
+ |
|
| 85 |
+func bindata_read(data, name string) ([]byte, error) {
|
|
| 86 |
+ var empty [0]byte |
|
| 87 |
+ sx := (*reflect.StringHeader)(unsafe.Pointer(&data)) |
|
| 88 |
+ b := empty[:] |
|
| 89 |
+ bx := (*reflect.SliceHeader)(unsafe.Pointer(&b)) |
|
| 90 |
+ bx.Data = sx.Data |
|
| 91 |
+ bx.Len = len(data) |
|
| 92 |
+ bx.Cap = bx.Len |
|
| 93 |
+ |
|
| 94 |
+ gz, err := gzip.NewReader(bytes.NewBuffer(b)) |
|
| 95 |
+ if err != nil {
|
|
| 96 |
+ return nil, fmt.Errorf("Read %%q: %%v", name, err)
|
|
| 97 |
+ } |
|
| 98 |
+ |
|
| 99 |
+ var buf bytes.Buffer |
|
| 100 |
+ _, err = io.Copy(&buf, gz) |
|
| 101 |
+ gz.Close() |
|
| 102 |
+ |
|
| 103 |
+ if err != nil {
|
|
| 104 |
+ return nil, fmt.Errorf("Read %%q: %%v", name, err)
|
|
| 105 |
+ } |
|
| 106 |
+ |
|
| 107 |
+ return buf.Bytes(), nil |
|
| 108 |
+} |
|
| 109 |
+ |
|
| 110 |
+`) |
|
| 111 |
+ return err |
|
| 112 |
+} |
|
| 113 |
+ |
|
| 114 |
+func header_compressed_memcopy(w io.Writer) error {
|
|
| 115 |
+ _, err := fmt.Fprintf(w, `import ( |
|
| 116 |
+ "bytes" |
|
| 117 |
+ "compress/gzip" |
|
| 118 |
+ "fmt" |
|
| 119 |
+ "io" |
|
| 120 |
+ "strings" |
|
| 121 |
+) |
|
| 122 |
+ |
|
| 123 |
+func bindata_read(data []byte, name string) ([]byte, error) {
|
|
| 124 |
+ gz, err := gzip.NewReader(bytes.NewBuffer(data)) |
|
| 125 |
+ if err != nil {
|
|
| 126 |
+ return nil, fmt.Errorf("Read %%q: %%v", name, err)
|
|
| 127 |
+ } |
|
| 128 |
+ |
|
| 129 |
+ var buf bytes.Buffer |
|
| 130 |
+ _, err = io.Copy(&buf, gz) |
|
| 131 |
+ gz.Close() |
|
| 132 |
+ |
|
| 133 |
+ if err != nil {
|
|
| 134 |
+ return nil, fmt.Errorf("Read %%q: %%v", name, err)
|
|
| 135 |
+ } |
|
| 136 |
+ |
|
| 137 |
+ return buf.Bytes(), nil |
|
| 138 |
+} |
|
| 139 |
+ |
|
| 140 |
+`) |
|
| 141 |
+ return err |
|
| 142 |
+} |
|
| 143 |
+ |
|
| 144 |
+func header_uncompressed_nomemcopy(w io.Writer) error {
|
|
| 145 |
+ _, err := fmt.Fprintf(w, `import ( |
|
| 146 |
+ "fmt" |
|
| 147 |
+ "reflect" |
|
| 148 |
+ "strings" |
|
| 149 |
+ "unsafe" |
|
| 150 |
+) |
|
| 151 |
+ |
|
| 152 |
+func bindata_read(data, name string) ([]byte, error) {
|
|
| 153 |
+ var empty [0]byte |
|
| 154 |
+ sx := (*reflect.StringHeader)(unsafe.Pointer(&data)) |
|
| 155 |
+ b := empty[:] |
|
| 156 |
+ bx := (*reflect.SliceHeader)(unsafe.Pointer(&b)) |
|
| 157 |
+ bx.Data = sx.Data |
|
| 158 |
+ bx.Len = len(data) |
|
| 159 |
+ bx.Cap = bx.Len |
|
| 160 |
+ return b, nil |
|
| 161 |
+} |
|
| 162 |
+ |
|
| 163 |
+`) |
|
| 164 |
+ return err |
|
| 165 |
+} |
|
| 166 |
+ |
|
| 167 |
+func header_uncompressed_memcopy(w io.Writer) error {
|
|
| 168 |
+ _, err := fmt.Fprintf(w, `import ( |
|
| 169 |
+ "fmt" |
|
| 170 |
+ "strings" |
|
| 171 |
+) |
|
| 172 |
+`) |
|
| 173 |
+ return err |
|
| 174 |
+} |
|
| 175 |
+ |
|
| 176 |
+func compressed_nomemcopy(w io.Writer, asset *Asset, r io.Reader) error {
|
|
| 177 |
+ _, err := fmt.Fprintf(w, `var _%s = "`, asset.Func) |
|
| 178 |
+ if err != nil {
|
|
| 179 |
+ return err |
|
| 180 |
+ } |
|
| 181 |
+ |
|
| 182 |
+ gz := gzip.NewWriter(&StringWriter{Writer: w})
|
|
| 183 |
+ _, err = io.Copy(gz, r) |
|
| 184 |
+ gz.Close() |
|
| 185 |
+ |
|
| 186 |
+ if err != nil {
|
|
| 187 |
+ return err |
|
| 188 |
+ } |
|
| 189 |
+ |
|
| 190 |
+ _, err = fmt.Fprintf(w, `" |
|
| 191 |
+ |
|
| 192 |
+func %s() ([]byte, error) {
|
|
| 193 |
+ return bindata_read( |
|
| 194 |
+ _%s, |
|
| 195 |
+ %q, |
|
| 196 |
+ ) |
|
| 197 |
+} |
|
| 198 |
+ |
|
| 199 |
+`, asset.Func, asset.Func, asset.Name) |
|
| 200 |
+ return err |
|
| 201 |
+} |
|
| 202 |
+ |
|
| 203 |
+func compressed_memcopy(w io.Writer, asset *Asset, r io.Reader) error {
|
|
| 204 |
+ _, err := fmt.Fprintf(w, `func %s() ([]byte, error) {
|
|
| 205 |
+ return bindata_read([]byte{`, asset.Func)
|
|
| 206 |
+ |
|
| 207 |
+ if err != nil {
|
|
| 208 |
+ return nil |
|
| 209 |
+ } |
|
| 210 |
+ |
|
| 211 |
+ gz := gzip.NewWriter(&ByteWriter{Writer: w})
|
|
| 212 |
+ _, err = io.Copy(gz, r) |
|
| 213 |
+ gz.Close() |
|
| 214 |
+ |
|
| 215 |
+ if err != nil {
|
|
| 216 |
+ return err |
|
| 217 |
+ } |
|
| 218 |
+ |
|
| 219 |
+ _, err = fmt.Fprintf(w, ` |
|
| 220 |
+ }, |
|
| 221 |
+ %q, |
|
| 222 |
+ ) |
|
| 223 |
+} |
|
| 224 |
+ |
|
| 225 |
+`, asset.Name) |
|
| 226 |
+ return err |
|
| 227 |
+} |
|
| 228 |
+ |
|
| 229 |
+func uncompressed_nomemcopy(w io.Writer, asset *Asset, r io.Reader) error {
|
|
| 230 |
+ _, err := fmt.Fprintf(w, `var _%s = "`, asset.Func) |
|
| 231 |
+ if err != nil {
|
|
| 232 |
+ return err |
|
| 233 |
+ } |
|
| 234 |
+ |
|
| 235 |
+ _, err = io.Copy(&StringWriter{Writer: w}, r)
|
|
| 236 |
+ if err != nil {
|
|
| 237 |
+ return err |
|
| 238 |
+ } |
|
| 239 |
+ |
|
| 240 |
+ _, err = fmt.Fprintf(w, `" |
|
| 241 |
+ |
|
| 242 |
+func %s() ([]byte, error) {
|
|
| 243 |
+ return bindata_read( |
|
| 244 |
+ _%s, |
|
| 245 |
+ %q, |
|
| 246 |
+ ) |
|
| 247 |
+} |
|
| 248 |
+ |
|
| 249 |
+`, asset.Func, asset.Func, asset.Name) |
|
| 250 |
+ return err |
|
| 251 |
+} |
|
| 252 |
+ |
|
| 253 |
+func uncompressed_memcopy(w io.Writer, asset *Asset, r io.Reader) error {
|
|
| 254 |
+ _, err := fmt.Fprintf(w, `func %s() ([]byte, error) {
|
|
| 255 |
+ return []byte{`, asset.Func)
|
|
| 256 |
+ if err != nil {
|
|
| 257 |
+ return err |
|
| 258 |
+ } |
|
| 259 |
+ |
|
| 260 |
+ _, err = io.Copy(&ByteWriter{Writer: w}, r)
|
|
| 261 |
+ if err != nil {
|
|
| 262 |
+ return err |
|
| 263 |
+ } |
|
| 264 |
+ |
|
| 265 |
+ _, err = fmt.Fprintf(w, ` |
|
| 266 |
+ }, nil |
|
| 267 |
+} |
|
| 268 |
+ |
|
| 269 |
+`) |
|
| 270 |
+ return err |
|
| 271 |
+} |
| 0 | 272 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,36 @@ |
| 0 |
+// This work is subject to the CC0 1.0 Universal (CC0 1.0) Public Domain Dedication |
|
| 1 |
+// license. Its contents can be found at: |
|
| 2 |
+// http://creativecommons.org/publicdomain/zero/1.0/ |
|
| 3 |
+ |
|
| 4 |
+package bindata |
|
| 5 |
+ |
|
| 6 |
+import ( |
|
| 7 |
+ "io" |
|
| 8 |
+) |
|
| 9 |
+ |
|
| 10 |
+const lowerHex = "0123456789abcdef" |
|
| 11 |
+ |
|
| 12 |
+type StringWriter struct {
|
|
| 13 |
+ io.Writer |
|
| 14 |
+ c int |
|
| 15 |
+} |
|
| 16 |
+ |
|
| 17 |
+func (w *StringWriter) Write(p []byte) (n int, err error) {
|
|
| 18 |
+ if len(p) == 0 {
|
|
| 19 |
+ return |
|
| 20 |
+ } |
|
| 21 |
+ |
|
| 22 |
+ buf := []byte(`\x00`) |
|
| 23 |
+ var b byte |
|
| 24 |
+ |
|
| 25 |
+ for n, b = range p {
|
|
| 26 |
+ buf[2] = lowerHex[b/16] |
|
| 27 |
+ buf[3] = lowerHex[b%16] |
|
| 28 |
+ w.Writer.Write(buf) |
|
| 29 |
+ w.c++ |
|
| 30 |
+ } |
|
| 31 |
+ |
|
| 32 |
+ n++ |
|
| 33 |
+ |
|
| 34 |
+ return |
|
| 35 |
+} |
| 0 | 1 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,86 @@ |
| 0 |
+package main |
|
| 1 |
+ |
|
| 2 |
+import ( |
|
| 3 |
+ "bytes" |
|
| 4 |
+ "compress/gzip" |
|
| 5 |
+ "io" |
|
| 6 |
+ "log" |
|
| 7 |
+) |
|
| 8 |
+ |
|
| 9 |
+func bindata_read(data []byte, name string) []byte {
|
|
| 10 |
+ gz, err := gzip.NewReader(bytes.NewBuffer(data)) |
|
| 11 |
+ if err != nil {
|
|
| 12 |
+ log.Fatalf("Read %q: %v", name, err)
|
|
| 13 |
+ } |
|
| 14 |
+ |
|
| 15 |
+ var buf bytes.Buffer |
|
| 16 |
+ _, err = io.Copy(&buf, gz) |
|
| 17 |
+ gz.Close() |
|
| 18 |
+ |
|
| 19 |
+ if err != nil {
|
|
| 20 |
+ log.Fatalf("Read %q: %v", name, err)
|
|
| 21 |
+ } |
|
| 22 |
+ |
|
| 23 |
+ return buf.Bytes() |
|
| 24 |
+} |
|
| 25 |
+ |
|
| 26 |
+func in_b_test_asset() []byte {
|
|
| 27 |
+ return bindata_read([]byte{
|
|
| 28 |
+ 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x00, 0xff, 0xd2, 0xd7, |
|
| 29 |
+ 0x57, 0x28, 0x4e, 0xcc, 0x2d, 0xc8, 0x49, 0x55, 0x48, 0xcb, 0xcc, 0x49, |
|
| 30 |
+ 0xe5, 0x02, 0x04, 0x00, 0x00, 0xff, 0xff, 0x8a, 0x82, 0x8c, 0x85, 0x0f, |
|
| 31 |
+ 0x00, 0x00, 0x00, |
|
| 32 |
+ }, |
|
| 33 |
+ "in/b/test.asset", |
|
| 34 |
+ ) |
|
| 35 |
+} |
|
| 36 |
+ |
|
| 37 |
+func in_test_asset() []byte {
|
|
| 38 |
+ return bindata_read([]byte{
|
|
| 39 |
+ 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x00, 0xff, 0xd2, 0xd7, |
|
| 40 |
+ 0x57, 0x28, 0x4e, 0xcc, 0x2d, 0xc8, 0x49, 0x55, 0x48, 0xcb, 0xcc, 0x49, |
|
| 41 |
+ 0xe5, 0x02, 0x04, 0x00, 0x00, 0xff, 0xff, 0x8a, 0x82, 0x8c, 0x85, 0x0f, |
|
| 42 |
+ 0x00, 0x00, 0x00, |
|
| 43 |
+ }, |
|
| 44 |
+ "in/test.asset", |
|
| 45 |
+ ) |
|
| 46 |
+} |
|
| 47 |
+ |
|
| 48 |
+func in_a_test_asset() []byte {
|
|
| 49 |
+ return bindata_read([]byte{
|
|
| 50 |
+ 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x00, 0xff, 0xd2, 0xd7, |
|
| 51 |
+ 0x57, 0x28, 0x4e, 0xcc, 0x2d, 0xc8, 0x49, 0x55, 0x48, 0xcb, 0xcc, 0x49, |
|
| 52 |
+ 0xe5, 0x02, 0x04, 0x00, 0x00, 0xff, 0xff, 0x8a, 0x82, 0x8c, 0x85, 0x0f, |
|
| 53 |
+ 0x00, 0x00, 0x00, |
|
| 54 |
+ }, |
|
| 55 |
+ "in/a/test.asset", |
|
| 56 |
+ ) |
|
| 57 |
+} |
|
| 58 |
+ |
|
| 59 |
+func in_c_test_asset() []byte {
|
|
| 60 |
+ return bindata_read([]byte{
|
|
| 61 |
+ 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x00, 0xff, 0xd2, 0xd7, |
|
| 62 |
+ 0x57, 0x28, 0x4e, 0xcc, 0x2d, 0xc8, 0x49, 0x55, 0x48, 0xcb, 0xcc, 0x49, |
|
| 63 |
+ 0xe5, 0x02, 0x04, 0x00, 0x00, 0xff, 0xff, 0x8a, 0x82, 0x8c, 0x85, 0x0f, |
|
| 64 |
+ 0x00, 0x00, 0x00, |
|
| 65 |
+ }, |
|
| 66 |
+ "in/c/test.asset", |
|
| 67 |
+ ) |
|
| 68 |
+} |
|
| 69 |
+ |
|
| 70 |
+// Asset loads and returns the asset for the given name. |
|
| 71 |
+// This returns nil of the asset could not be found. |
|
| 72 |
+func Asset(name string) []byte {
|
|
| 73 |
+ if f, ok := _bindata[name]; ok {
|
|
| 74 |
+ return f() |
|
| 75 |
+ } |
|
| 76 |
+ return nil |
|
| 77 |
+} |
|
| 78 |
+ |
|
| 79 |
+// _bindata is a table, holding each asset generator, mapped to its name. |
|
| 80 |
+var _bindata = map[string]func() []byte{
|
|
| 81 |
+ "in/b/test.asset": in_b_test_asset, |
|
| 82 |
+ "in/test.asset": in_test_asset, |
|
| 83 |
+ "in/a/test.asset": in_a_test_asset, |
|
| 84 |
+ "in/c/test.asset": in_c_test_asset, |
|
| 85 |
+} |
| 0 | 86 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,88 @@ |
| 0 |
+package main |
|
| 1 |
+ |
|
| 2 |
+import ( |
|
| 3 |
+ "bytes" |
|
| 4 |
+ "compress/gzip" |
|
| 5 |
+ "io" |
|
| 6 |
+ "log" |
|
| 7 |
+ "reflect" |
|
| 8 |
+ "unsafe" |
|
| 9 |
+) |
|
| 10 |
+ |
|
| 11 |
+func bindata_read(data, name string) []byte {
|
|
| 12 |
+ var empty [0]byte |
|
| 13 |
+ sx := (*reflect.StringHeader)(unsafe.Pointer(&data)) |
|
| 14 |
+ b := empty[:] |
|
| 15 |
+ bx := (*reflect.SliceHeader)(unsafe.Pointer(&b)) |
|
| 16 |
+ bx.Data = sx.Data |
|
| 17 |
+ bx.Len = len(data) |
|
| 18 |
+ bx.Cap = bx.Len |
|
| 19 |
+ |
|
| 20 |
+ gz, err := gzip.NewReader(bytes.NewBuffer(b)) |
|
| 21 |
+ if err != nil {
|
|
| 22 |
+ log.Fatalf("Read %q: %v", name, err)
|
|
| 23 |
+ } |
|
| 24 |
+ |
|
| 25 |
+ var buf bytes.Buffer |
|
| 26 |
+ _, err = io.Copy(&buf, gz) |
|
| 27 |
+ gz.Close() |
|
| 28 |
+ |
|
| 29 |
+ if err != nil {
|
|
| 30 |
+ log.Fatalf("Read %q: %v", name, err)
|
|
| 31 |
+ } |
|
| 32 |
+ |
|
| 33 |
+ return buf.Bytes() |
|
| 34 |
+} |
|
| 35 |
+ |
|
| 36 |
+var _in_b_test_asset = "\x1f\x8b\x08\x00\x00\x09\x6e\x88\x00\xff\xd2\xd7\x57\x28\x4e\xcc\x2d\xc8\x49\x55\x48\xcb\xcc\x49\xe5\x02\x04\x00\x00\xff\xff\x8a\x82\x8c\x85\x0f\x00\x00\x00" |
|
| 37 |
+ |
|
| 38 |
+func in_b_test_asset() []byte {
|
|
| 39 |
+ return bindata_read( |
|
| 40 |
+ _in_b_test_asset, |
|
| 41 |
+ "in/b/test.asset", |
|
| 42 |
+ ) |
|
| 43 |
+} |
|
| 44 |
+ |
|
| 45 |
+var _in_test_asset = "\x1f\x8b\x08\x00\x00\x09\x6e\x88\x00\xff\xd2\xd7\x57\x28\x4e\xcc\x2d\xc8\x49\x55\x48\xcb\xcc\x49\xe5\x02\x04\x00\x00\xff\xff\x8a\x82\x8c\x85\x0f\x00\x00\x00" |
|
| 46 |
+ |
|
| 47 |
+func in_test_asset() []byte {
|
|
| 48 |
+ return bindata_read( |
|
| 49 |
+ _in_test_asset, |
|
| 50 |
+ "in/test.asset", |
|
| 51 |
+ ) |
|
| 52 |
+} |
|
| 53 |
+ |
|
| 54 |
+var _in_a_test_asset = "\x1f\x8b\x08\x00\x00\x09\x6e\x88\x00\xff\xd2\xd7\x57\x28\x4e\xcc\x2d\xc8\x49\x55\x48\xcb\xcc\x49\xe5\x02\x04\x00\x00\xff\xff\x8a\x82\x8c\x85\x0f\x00\x00\x00" |
|
| 55 |
+ |
|
| 56 |
+func in_a_test_asset() []byte {
|
|
| 57 |
+ return bindata_read( |
|
| 58 |
+ _in_a_test_asset, |
|
| 59 |
+ "in/a/test.asset", |
|
| 60 |
+ ) |
|
| 61 |
+} |
|
| 62 |
+ |
|
| 63 |
+var _in_c_test_asset = "\x1f\x8b\x08\x00\x00\x09\x6e\x88\x00\xff\xd2\xd7\x57\x28\x4e\xcc\x2d\xc8\x49\x55\x48\xcb\xcc\x49\xe5\x02\x04\x00\x00\xff\xff\x8a\x82\x8c\x85\x0f\x00\x00\x00" |
|
| 64 |
+ |
|
| 65 |
+func in_c_test_asset() []byte {
|
|
| 66 |
+ return bindata_read( |
|
| 67 |
+ _in_c_test_asset, |
|
| 68 |
+ "in/c/test.asset", |
|
| 69 |
+ ) |
|
| 70 |
+} |
|
| 71 |
+ |
|
| 72 |
+// Asset loads and returns the asset for the given name. |
|
| 73 |
+// This returns nil of the asset could not be found. |
|
| 74 |
+func Asset(name string) []byte {
|
|
| 75 |
+ if f, ok := _bindata[name]; ok {
|
|
| 76 |
+ return f() |
|
| 77 |
+ } |
|
| 78 |
+ return nil |
|
| 79 |
+} |
|
| 80 |
+ |
|
| 81 |
+// _bindata is a table, holding each asset generator, mapped to its name. |
|
| 82 |
+var _bindata = map[string]func() []byte{
|
|
| 83 |
+ "in/b/test.asset": in_b_test_asset, |
|
| 84 |
+ "in/test.asset": in_test_asset, |
|
| 85 |
+ "in/a/test.asset": in_a_test_asset, |
|
| 86 |
+ "in/c/test.asset": in_c_test_asset, |
|
| 87 |
+} |
| 0 | 88 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,80 @@ |
| 0 |
+package main |
|
| 1 |
+ |
|
| 2 |
+import ( |
|
| 3 |
+ "bytes" |
|
| 4 |
+ "io" |
|
| 5 |
+ "log" |
|
| 6 |
+ "os" |
|
| 7 |
+) |
|
| 8 |
+ |
|
| 9 |
+// bindata_read reads the given file from disk. |
|
| 10 |
+// It panics if anything went wrong. |
|
| 11 |
+func bindata_read(path, name string) []byte {
|
|
| 12 |
+ fd, err := os.Open(path) |
|
| 13 |
+ if err != nil {
|
|
| 14 |
+ log.Fatalf("Read %s: %v", name, err)
|
|
| 15 |
+ } |
|
| 16 |
+ |
|
| 17 |
+ defer fd.Close() |
|
| 18 |
+ |
|
| 19 |
+ var buf bytes.Buffer |
|
| 20 |
+ _, err = io.Copy(&buf, fd) |
|
| 21 |
+ if err != nil {
|
|
| 22 |
+ log.Fatalf("Read %s: %v", name, err)
|
|
| 23 |
+ } |
|
| 24 |
+ |
|
| 25 |
+ return buf.Bytes() |
|
| 26 |
+} |
|
| 27 |
+ |
|
| 28 |
+// in_b_test_asset reads file data from disk. |
|
| 29 |
+// It panics if something went wrong in the process. |
|
| 30 |
+func in_b_test_asset() []byte {
|
|
| 31 |
+ return bindata_read( |
|
| 32 |
+ "/a/code/go/src/github.com/jteeuwen/go-bindata/testdata/in/b/test.asset", |
|
| 33 |
+ "in/b/test.asset", |
|
| 34 |
+ ) |
|
| 35 |
+} |
|
| 36 |
+ |
|
| 37 |
+// in_test_asset reads file data from disk. |
|
| 38 |
+// It panics if something went wrong in the process. |
|
| 39 |
+func in_test_asset() []byte {
|
|
| 40 |
+ return bindata_read( |
|
| 41 |
+ "/a/code/go/src/github.com/jteeuwen/go-bindata/testdata/in/test.asset", |
|
| 42 |
+ "in/test.asset", |
|
| 43 |
+ ) |
|
| 44 |
+} |
|
| 45 |
+ |
|
| 46 |
+// in_a_test_asset reads file data from disk. |
|
| 47 |
+// It panics if something went wrong in the process. |
|
| 48 |
+func in_a_test_asset() []byte {
|
|
| 49 |
+ return bindata_read( |
|
| 50 |
+ "/a/code/go/src/github.com/jteeuwen/go-bindata/testdata/in/a/test.asset", |
|
| 51 |
+ "in/a/test.asset", |
|
| 52 |
+ ) |
|
| 53 |
+} |
|
| 54 |
+ |
|
| 55 |
+// in_c_test_asset reads file data from disk. |
|
| 56 |
+// It panics if something went wrong in the process. |
|
| 57 |
+func in_c_test_asset() []byte {
|
|
| 58 |
+ return bindata_read( |
|
| 59 |
+ "/a/code/go/src/github.com/jteeuwen/go-bindata/testdata/in/c/test.asset", |
|
| 60 |
+ "in/c/test.asset", |
|
| 61 |
+ ) |
|
| 62 |
+} |
|
| 63 |
+ |
|
| 64 |
+// Asset loads and returns the asset for the given name. |
|
| 65 |
+// This returns nil of the asset could not be found. |
|
| 66 |
+func Asset(name string) []byte {
|
|
| 67 |
+ if f, ok := _bindata[name]; ok {
|
|
| 68 |
+ return f() |
|
| 69 |
+ } |
|
| 70 |
+ return nil |
|
| 71 |
+} |
|
| 72 |
+ |
|
| 73 |
+// _bindata is a table, holding each asset generator, mapped to its name. |
|
| 74 |
+var _bindata = map[string]func() []byte{
|
|
| 75 |
+ "in/b/test.asset": in_b_test_asset, |
|
| 76 |
+ "in/test.asset": in_test_asset, |
|
| 77 |
+ "in/a/test.asset": in_a_test_asset, |
|
| 78 |
+ "in/c/test.asset": in_c_test_asset, |
|
| 79 |
+} |
| 0 | 80 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,46 @@ |
| 0 |
+package main |
|
| 1 |
+ |
|
| 2 |
+func in_b_test_asset() []byte {
|
|
| 3 |
+ return []byte{
|
|
| 4 |
+ 0x2f, 0x2f, 0x20, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x20, 0x66, 0x69, |
|
| 5 |
+ 0x6c, 0x65, 0x0a, |
|
| 6 |
+ } |
|
| 7 |
+} |
|
| 8 |
+ |
|
| 9 |
+func in_test_asset() []byte {
|
|
| 10 |
+ return []byte{
|
|
| 11 |
+ 0x2f, 0x2f, 0x20, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x20, 0x66, 0x69, |
|
| 12 |
+ 0x6c, 0x65, 0x0a, |
|
| 13 |
+ } |
|
| 14 |
+} |
|
| 15 |
+ |
|
| 16 |
+func in_a_test_asset() []byte {
|
|
| 17 |
+ return []byte{
|
|
| 18 |
+ 0x2f, 0x2f, 0x20, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x20, 0x66, 0x69, |
|
| 19 |
+ 0x6c, 0x65, 0x0a, |
|
| 20 |
+ } |
|
| 21 |
+} |
|
| 22 |
+ |
|
| 23 |
+func in_c_test_asset() []byte {
|
|
| 24 |
+ return []byte{
|
|
| 25 |
+ 0x2f, 0x2f, 0x20, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x20, 0x66, 0x69, |
|
| 26 |
+ 0x6c, 0x65, 0x0a, |
|
| 27 |
+ } |
|
| 28 |
+} |
|
| 29 |
+ |
|
| 30 |
+// Asset loads and returns the asset for the given name. |
|
| 31 |
+// This returns nil of the asset could not be found. |
|
| 32 |
+func Asset(name string) []byte {
|
|
| 33 |
+ if f, ok := _bindata[name]; ok {
|
|
| 34 |
+ return f() |
|
| 35 |
+ } |
|
| 36 |
+ return nil |
|
| 37 |
+} |
|
| 38 |
+ |
|
| 39 |
+// _bindata is a table, holding each asset generator, mapped to its name. |
|
| 40 |
+var _bindata = map[string]func() []byte{
|
|
| 41 |
+ "in/b/test.asset": in_b_test_asset, |
|
| 42 |
+ "in/test.asset": in_test_asset, |
|
| 43 |
+ "in/a/test.asset": in_a_test_asset, |
|
| 44 |
+ "in/c/test.asset": in_c_test_asset, |
|
| 45 |
+} |
| 0 | 46 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,70 @@ |
| 0 |
+package main |
|
| 1 |
+ |
|
| 2 |
+import ( |
|
| 3 |
+ "reflect" |
|
| 4 |
+ "unsafe" |
|
| 5 |
+) |
|
| 6 |
+ |
|
| 7 |
+func bindata_read(data, name string) []byte {
|
|
| 8 |
+ var empty [0]byte |
|
| 9 |
+ sx := (*reflect.StringHeader)(unsafe.Pointer(&data)) |
|
| 10 |
+ b := empty[:] |
|
| 11 |
+ bx := (*reflect.SliceHeader)(unsafe.Pointer(&b)) |
|
| 12 |
+ bx.Data = sx.Data |
|
| 13 |
+ bx.Len = len(data) |
|
| 14 |
+ bx.Cap = bx.Len |
|
| 15 |
+ return b |
|
| 16 |
+} |
|
| 17 |
+ |
|
| 18 |
+var _in_b_test_asset = "\x2f\x2f\x20\x73\x61\x6d\x70\x6c\x65\x20\x66\x69\x6c\x65\x0a" |
|
| 19 |
+ |
|
| 20 |
+func in_b_test_asset() []byte {
|
|
| 21 |
+ return bindata_read( |
|
| 22 |
+ _in_b_test_asset, |
|
| 23 |
+ "in/b/test.asset", |
|
| 24 |
+ ) |
|
| 25 |
+} |
|
| 26 |
+ |
|
| 27 |
+var _in_test_asset = "\x2f\x2f\x20\x73\x61\x6d\x70\x6c\x65\x20\x66\x69\x6c\x65\x0a" |
|
| 28 |
+ |
|
| 29 |
+func in_test_asset() []byte {
|
|
| 30 |
+ return bindata_read( |
|
| 31 |
+ _in_test_asset, |
|
| 32 |
+ "in/test.asset", |
|
| 33 |
+ ) |
|
| 34 |
+} |
|
| 35 |
+ |
|
| 36 |
+var _in_a_test_asset = "\x2f\x2f\x20\x73\x61\x6d\x70\x6c\x65\x20\x66\x69\x6c\x65\x0a" |
|
| 37 |
+ |
|
| 38 |
+func in_a_test_asset() []byte {
|
|
| 39 |
+ return bindata_read( |
|
| 40 |
+ _in_a_test_asset, |
|
| 41 |
+ "in/a/test.asset", |
|
| 42 |
+ ) |
|
| 43 |
+} |
|
| 44 |
+ |
|
| 45 |
+var _in_c_test_asset = "\x2f\x2f\x20\x73\x61\x6d\x70\x6c\x65\x20\x66\x69\x6c\x65\x0a" |
|
| 46 |
+ |
|
| 47 |
+func in_c_test_asset() []byte {
|
|
| 48 |
+ return bindata_read( |
|
| 49 |
+ _in_c_test_asset, |
|
| 50 |
+ "in/c/test.asset", |
|
| 51 |
+ ) |
|
| 52 |
+} |
|
| 53 |
+ |
|
| 54 |
+// Asset loads and returns the asset for the given name. |
|
| 55 |
+// This returns nil of the asset could not be found. |
|
| 56 |
+func Asset(name string) []byte {
|
|
| 57 |
+ if f, ok := _bindata[name]; ok {
|
|
| 58 |
+ return f() |
|
| 59 |
+ } |
|
| 60 |
+ return nil |
|
| 61 |
+} |
|
| 62 |
+ |
|
| 63 |
+// _bindata is a table, holding each asset generator, mapped to its name. |
|
| 64 |
+var _bindata = map[string]func() []byte{
|
|
| 65 |
+ "in/b/test.asset": in_b_test_asset, |
|
| 66 |
+ "in/test.asset": in_test_asset, |
|
| 67 |
+ "in/a/test.asset": in_a_test_asset, |
|
| 68 |
+ "in/c/test.asset": in_c_test_asset, |
|
| 69 |
+} |
| 0 | 70 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,184 @@ |
| 0 |
+// This work is subject to the CC0 1.0 Universal (CC0 1.0) Public Domain Dedication |
|
| 1 |
+// license. Its contents can be found at: |
|
| 2 |
+// http://creativecommons.org/publicdomain/zero/1.0/ |
|
| 3 |
+ |
|
| 4 |
+package bindata |
|
| 5 |
+ |
|
| 6 |
+import ( |
|
| 7 |
+ "fmt" |
|
| 8 |
+ "io" |
|
| 9 |
+ "os" |
|
| 10 |
+ "strings" |
|
| 11 |
+) |
|
| 12 |
+ |
|
| 13 |
+type assetTree struct {
|
|
| 14 |
+ Asset Asset |
|
| 15 |
+ Children map[string]*assetTree |
|
| 16 |
+} |
|
| 17 |
+ |
|
| 18 |
+func newAssetTree() *assetTree {
|
|
| 19 |
+ tree := &assetTree{}
|
|
| 20 |
+ tree.Children = make(map[string]*assetTree) |
|
| 21 |
+ return tree |
|
| 22 |
+} |
|
| 23 |
+ |
|
| 24 |
+func (node *assetTree) child(name string) *assetTree {
|
|
| 25 |
+ rv, ok := node.Children[name] |
|
| 26 |
+ if !ok {
|
|
| 27 |
+ rv = newAssetTree() |
|
| 28 |
+ node.Children[name] = rv |
|
| 29 |
+ } |
|
| 30 |
+ return rv |
|
| 31 |
+} |
|
| 32 |
+ |
|
| 33 |
+func (root *assetTree) Add(route []string, asset Asset) {
|
|
| 34 |
+ for _, name := range route {
|
|
| 35 |
+ root = root.child(name) |
|
| 36 |
+ } |
|
| 37 |
+ root.Asset = asset |
|
| 38 |
+} |
|
| 39 |
+ |
|
| 40 |
+func ident(w io.Writer, n int) {
|
|
| 41 |
+ for i := 0; i < n; i++ {
|
|
| 42 |
+ w.Write([]byte{'\t'})
|
|
| 43 |
+ } |
|
| 44 |
+} |
|
| 45 |
+ |
|
| 46 |
+func (root *assetTree) funcOrNil() string {
|
|
| 47 |
+ if root.Asset.Func == "" {
|
|
| 48 |
+ return "nil" |
|
| 49 |
+ } else {
|
|
| 50 |
+ return root.Asset.Func |
|
| 51 |
+ } |
|
| 52 |
+} |
|
| 53 |
+ |
|
| 54 |
+func (root *assetTree) writeGoMap(w io.Writer, nident int) {
|
|
| 55 |
+ fmt.Fprintf(w, "&_bintree_t{%s, map[string]*_bintree_t{\n", root.funcOrNil())
|
|
| 56 |
+ for p, child := range root.Children {
|
|
| 57 |
+ ident(w, nident+1) |
|
| 58 |
+ fmt.Fprintf(w, `"%s": `, p) |
|
| 59 |
+ child.writeGoMap(w, nident+1) |
|
| 60 |
+ } |
|
| 61 |
+ ident(w, nident) |
|
| 62 |
+ io.WriteString(w, "}}") |
|
| 63 |
+ if nident > 0 {
|
|
| 64 |
+ io.WriteString(w, ",") |
|
| 65 |
+ } |
|
| 66 |
+ io.WriteString(w, "\n") |
|
| 67 |
+} |
|
| 68 |
+ |
|
| 69 |
+func (root *assetTree) WriteAsGoMap(w io.Writer) error {
|
|
| 70 |
+ _, err := fmt.Fprint(w, `type _bintree_t struct {
|
|
| 71 |
+ Func func() ([]byte, error) |
|
| 72 |
+ Children map[string]*_bintree_t |
|
| 73 |
+} |
|
| 74 |
+var _bintree = `) |
|
| 75 |
+ root.writeGoMap(w, 0) |
|
| 76 |
+ return err |
|
| 77 |
+} |
|
| 78 |
+ |
|
| 79 |
+func writeTOCTree(w io.Writer, toc []Asset) error {
|
|
| 80 |
+ _, err := fmt.Fprintf(w, `// AssetDir returns the file names below a certain |
|
| 81 |
+// directory embedded in the file by go-bindata. |
|
| 82 |
+// For example if you run go-bindata on data/... and data contains the |
|
| 83 |
+// following hierarchy: |
|
| 84 |
+// data/ |
|
| 85 |
+// foo.txt |
|
| 86 |
+// img/ |
|
| 87 |
+// a.png |
|
| 88 |
+// b.png |
|
| 89 |
+// then AssetDir("data") would return []string{"foo.txt", "img"}
|
|
| 90 |
+// AssetDir("data/img") would return []string{"a.png", "b.png"}
|
|
| 91 |
+// AssetDir("foo.txt") and AssetDir("notexist") would return an error
|
|
| 92 |
+// AssetDir("") will return []string{"data"}.
|
|
| 93 |
+func AssetDir(name string) ([]string, error) {
|
|
| 94 |
+ node := _bintree |
|
| 95 |
+ if len(name) != 0 {
|
|
| 96 |
+ cannonicalName := strings.Replace(name, "\\", "/", -1) |
|
| 97 |
+ pathList := strings.Split(cannonicalName, "/") |
|
| 98 |
+ for _, p := range pathList {
|
|
| 99 |
+ node = node.Children[p] |
|
| 100 |
+ if node == nil {
|
|
| 101 |
+ return nil, fmt.Errorf("Asset %%s not found", name)
|
|
| 102 |
+ } |
|
| 103 |
+ } |
|
| 104 |
+ } |
|
| 105 |
+ if node.Func != nil {
|
|
| 106 |
+ return nil, fmt.Errorf("Asset %%s not found", name)
|
|
| 107 |
+ } |
|
| 108 |
+ rv := make([]string, 0, len(node.Children)) |
|
| 109 |
+ for name := range node.Children {
|
|
| 110 |
+ rv = append(rv, name) |
|
| 111 |
+ } |
|
| 112 |
+ return rv, nil |
|
| 113 |
+} |
|
| 114 |
+ |
|
| 115 |
+`) |
|
| 116 |
+ if err != nil {
|
|
| 117 |
+ return err |
|
| 118 |
+ } |
|
| 119 |
+ tree := newAssetTree() |
|
| 120 |
+ for i := range toc {
|
|
| 121 |
+ pathList := strings.Split(toc[i].Name, string(os.PathSeparator)) |
|
| 122 |
+ tree.Add(pathList, toc[i]) |
|
| 123 |
+ } |
|
| 124 |
+ return tree.WriteAsGoMap(w) |
|
| 125 |
+} |
|
| 126 |
+ |
|
| 127 |
+// writeTOC writes the table of contents file. |
|
| 128 |
+func writeTOC(w io.Writer, toc []Asset) error {
|
|
| 129 |
+ err := writeTOCHeader(w) |
|
| 130 |
+ if err != nil {
|
|
| 131 |
+ return err |
|
| 132 |
+ } |
|
| 133 |
+ |
|
| 134 |
+ for i := range toc {
|
|
| 135 |
+ err = writeTOCAsset(w, &toc[i]) |
|
| 136 |
+ if err != nil {
|
|
| 137 |
+ return err |
|
| 138 |
+ } |
|
| 139 |
+ } |
|
| 140 |
+ |
|
| 141 |
+ return writeTOCFooter(w) |
|
| 142 |
+} |
|
| 143 |
+ |
|
| 144 |
+// writeTOCHeader writes the table of contents file header. |
|
| 145 |
+func writeTOCHeader(w io.Writer) error {
|
|
| 146 |
+ _, err := fmt.Fprintf(w, `// Asset loads and returns the asset for the given name. |
|
| 147 |
+// It returns an error if the asset could not be found or |
|
| 148 |
+// could not be loaded. |
|
| 149 |
+func Asset(name string) ([]byte, error) {
|
|
| 150 |
+ cannonicalName := strings.Replace(name, "\\", "/", -1) |
|
| 151 |
+ if f, ok := _bindata[cannonicalName]; ok {
|
|
| 152 |
+ return f() |
|
| 153 |
+ } |
|
| 154 |
+ return nil, fmt.Errorf("Asset %%s not found", name)
|
|
| 155 |
+} |
|
| 156 |
+ |
|
| 157 |
+// AssetNames returns the names of the assets. |
|
| 158 |
+func AssetNames() []string {
|
|
| 159 |
+ names := make([]string, 0, len(_bindata)) |
|
| 160 |
+ for name := range _bindata {
|
|
| 161 |
+ names = append(names, name) |
|
| 162 |
+ } |
|
| 163 |
+ return names |
|
| 164 |
+} |
|
| 165 |
+ |
|
| 166 |
+// _bindata is a table, holding each asset generator, mapped to its name. |
|
| 167 |
+var _bindata = map[string]func() ([]byte, error){
|
|
| 168 |
+`) |
|
| 169 |
+ return err |
|
| 170 |
+} |
|
| 171 |
+ |
|
| 172 |
+// writeTOCAsset write a TOC entry for the given asset. |
|
| 173 |
+func writeTOCAsset(w io.Writer, asset *Asset) error {
|
|
| 174 |
+ _, err := fmt.Fprintf(w, "\t%q: %s,\n", asset.Name, asset.Func) |
|
| 175 |
+ return err |
|
| 176 |
+} |
|
| 177 |
+ |
|
| 178 |
+// writeTOCFooter writes the table of contents file footer. |
|
| 179 |
+func writeTOCFooter(w io.Writer) error {
|
|
| 180 |
+ _, err := fmt.Fprintf(w, `} |
|
| 181 |
+`) |
|
| 182 |
+ return err |
|
| 183 |
+} |
| 0 | 3 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,21 @@ |
| 0 |
+# EditorConfig helps developers define and maintain consistent |
|
| 1 |
+# coding styles between different editors and IDEs |
|
| 2 |
+# editorconfig.org |
|
| 3 |
+ |
|
| 4 |
+root = true |
|
| 5 |
+ |
|
| 6 |
+ |
|
| 7 |
+[*] |
|
| 8 |
+ |
|
| 9 |
+# Change these settings to your own preference |
|
| 10 |
+indent_style = space |
|
| 11 |
+indent_size = 2 |
|
| 12 |
+ |
|
| 13 |
+# We recommend you to keep these unchanged |
|
| 14 |
+end_of_line = lf |
|
| 15 |
+charset = utf-8 |
|
| 16 |
+trim_trailing_whitespace = true |
|
| 17 |
+insert_final_newline = true |
|
| 18 |
+ |
|
| 19 |
+[*.md] |
|
| 20 |
+trim_trailing_whitespace = false |
| 0 | 5 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,23 @@ |
| 0 |
+{
|
|
| 1 |
+ "node": true, |
|
| 2 |
+ "browser": true, |
|
| 3 |
+ "esnext": true, |
|
| 4 |
+ "bitwise": true, |
|
| 5 |
+ "camelcase": true, |
|
| 6 |
+ "curly": true, |
|
| 7 |
+ "eqeqeq": true, |
|
| 8 |
+ "immed": true, |
|
| 9 |
+ "indent": 2, |
|
| 10 |
+ "latedef": true, |
|
| 11 |
+ "newcap": true, |
|
| 12 |
+ "noarg": true, |
|
| 13 |
+ "regexp": true, |
|
| 14 |
+ "undef": true, |
|
| 15 |
+ "unused": true, |
|
| 16 |
+ "strict": true, |
|
| 17 |
+ "trailing": true, |
|
| 18 |
+ "smarttabs": true, |
|
| 19 |
+ "globals": {
|
|
| 20 |
+ "angular": false |
|
| 21 |
+ } |
|
| 22 |
+} |
| 0 | 23 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,463 @@ |
| 0 |
+// Generated on 2014-09-12 using generator-angular 0.9.8 |
|
| 1 |
+'use strict'; |
|
| 2 |
+ |
|
| 3 |
+// # Globbing |
|
| 4 |
+// for performance reasons we're only matching one level down: |
|
| 5 |
+// 'test/spec/{,*/}*.js'
|
|
| 6 |
+// use this if you want to recursively match all subfolders: |
|
| 7 |
+// 'test/spec/**/*.js' |
|
| 8 |
+ |
|
| 9 |
+module.exports = function (grunt) {
|
|
| 10 |
+ |
|
| 11 |
+ // Load grunt tasks automatically |
|
| 12 |
+ require('load-grunt-tasks')(grunt, {
|
|
| 13 |
+ pattern: ['grunt-*', '!grunt-template-jasmine-istanbul'] |
|
| 14 |
+ }); |
|
| 15 |
+ |
|
| 16 |
+ // Time how long tasks take. Can help when optimizing build times |
|
| 17 |
+ require('time-grunt')(grunt);
|
|
| 18 |
+ |
|
| 19 |
+ // Configurable paths for the application |
|
| 20 |
+ var appConfig = {
|
|
| 21 |
+ app: require('./bower.json').appPath || 'app',
|
|
| 22 |
+ dist: 'dist' |
|
| 23 |
+ }; |
|
| 24 |
+ |
|
| 25 |
+ // Define the configuration for all the tasks |
|
| 26 |
+ grunt.initConfig({
|
|
| 27 |
+ |
|
| 28 |
+ // Project settings |
|
| 29 |
+ yeoman: appConfig, |
|
| 30 |
+ |
|
| 31 |
+ // Watches files for changes and runs tasks based on the changed files |
|
| 32 |
+ watch: {
|
|
| 33 |
+ bower: {
|
|
| 34 |
+ files: ['bower.json'], |
|
| 35 |
+ tasks: ['wiredep'] |
|
| 36 |
+ }, |
|
| 37 |
+ js: {
|
|
| 38 |
+ files: ['<%= yeoman.app %>/scripts/{,*/}*.js'],
|
|
| 39 |
+ tasks: ['newer:jshint:all'], |
|
| 40 |
+ options: {
|
|
| 41 |
+ livereload: '<%= connect.options.livereload %>' |
|
| 42 |
+ } |
|
| 43 |
+ }, |
|
| 44 |
+ jsTest: {
|
|
| 45 |
+ files: ['test/spec/{,*/}*.js'],
|
|
| 46 |
+ tasks: ['newer:jshint:test', 'karma'] |
|
| 47 |
+ }, |
|
| 48 |
+ compass: {
|
|
| 49 |
+ files: ['<%= yeoman.app %>/styles/{,*/}*.{scss,sass}'],
|
|
| 50 |
+ tasks: ['compass:server', 'autoprefixer'] |
|
| 51 |
+ }, |
|
| 52 |
+ gruntfile: {
|
|
| 53 |
+ files: ['Gruntfile.js'] |
|
| 54 |
+ }, |
|
| 55 |
+ livereload: {
|
|
| 56 |
+ options: {
|
|
| 57 |
+ livereload: '<%= connect.options.livereload %>' |
|
| 58 |
+ }, |
|
| 59 |
+ files: [ |
|
| 60 |
+ '<%= yeoman.app %>/{,*/}*.html',
|
|
| 61 |
+ '.tmp/styles/{,*/}*.css',
|
|
| 62 |
+ '<%= yeoman.app %>/images/{,*/}*.{png,jpg,jpeg,gif,webp,svg}'
|
|
| 63 |
+ ] |
|
| 64 |
+ } |
|
| 65 |
+ }, |
|
| 66 |
+ |
|
| 67 |
+ // The actual grunt server settings |
|
| 68 |
+ connect: {
|
|
| 69 |
+ options: {
|
|
| 70 |
+ port: 9000, |
|
| 71 |
+ // Change this to '0.0.0.0' to access the server from outside. |
|
| 72 |
+ hostname: 'localhost', |
|
| 73 |
+ livereload: 35729 |
|
| 74 |
+ }, |
|
| 75 |
+ livereload: {
|
|
| 76 |
+ options: {
|
|
| 77 |
+ open: true, |
|
| 78 |
+ middleware: function (connect) {
|
|
| 79 |
+ return [ |
|
| 80 |
+ connect.static('.tmp'),
|
|
| 81 |
+ connect().use( |
|
| 82 |
+ '/bower_components', |
|
| 83 |
+ connect.static('./bower_components')
|
|
| 84 |
+ ), |
|
| 85 |
+ connect.static(appConfig.app) |
|
| 86 |
+ ]; |
|
| 87 |
+ } |
|
| 88 |
+ } |
|
| 89 |
+ }, |
|
| 90 |
+ test: {
|
|
| 91 |
+ options: {
|
|
| 92 |
+ port: 9001, |
|
| 93 |
+ middleware: function (connect) {
|
|
| 94 |
+ return [ |
|
| 95 |
+ connect.static('.tmp'),
|
|
| 96 |
+ connect.static('test'),
|
|
| 97 |
+ connect().use( |
|
| 98 |
+ '/bower_components', |
|
| 99 |
+ connect.static('./bower_components')
|
|
| 100 |
+ ), |
|
| 101 |
+ connect.static(appConfig.app) |
|
| 102 |
+ ]; |
|
| 103 |
+ } |
|
| 104 |
+ } |
|
| 105 |
+ }, |
|
| 106 |
+ dist: {
|
|
| 107 |
+ options: {
|
|
| 108 |
+ open: true, |
|
| 109 |
+ base: '<%= yeoman.dist %>' |
|
| 110 |
+ } |
|
| 111 |
+ } |
|
| 112 |
+ }, |
|
| 113 |
+ |
|
| 114 |
+ // Make sure code styles are up to par and there are no obvious mistakes |
|
| 115 |
+ jshint: {
|
|
| 116 |
+ options: {
|
|
| 117 |
+ jshintrc: '.jshintrc', |
|
| 118 |
+ reporter: require('jshint-stylish')
|
|
| 119 |
+ }, |
|
| 120 |
+ all: {
|
|
| 121 |
+ src: [ |
|
| 122 |
+ 'Gruntfile.js', |
|
| 123 |
+ '<%= yeoman.app %>/scripts/{,*/}*.js'
|
|
| 124 |
+ ] |
|
| 125 |
+ }, |
|
| 126 |
+ test: {
|
|
| 127 |
+ options: {
|
|
| 128 |
+ jshintrc: 'test/.jshintrc' |
|
| 129 |
+ }, |
|
| 130 |
+ src: ['test/spec/{,*/}*.js']
|
|
| 131 |
+ } |
|
| 132 |
+ }, |
|
| 133 |
+ |
|
| 134 |
+ // Empties folders to start fresh |
|
| 135 |
+ clean: {
|
|
| 136 |
+ dist: {
|
|
| 137 |
+ files: [{
|
|
| 138 |
+ dot: true, |
|
| 139 |
+ src: [ |
|
| 140 |
+ '.tmp', |
|
| 141 |
+ '<%= yeoman.dist %>/{,*/}*',
|
|
| 142 |
+ '!<%= yeoman.dist %>/.git*' |
|
| 143 |
+ ] |
|
| 144 |
+ }] |
|
| 145 |
+ }, |
|
| 146 |
+ server: '.tmp' |
|
| 147 |
+ }, |
|
| 148 |
+ |
|
| 149 |
+ // Add vendor prefixed styles |
|
| 150 |
+ autoprefixer: {
|
|
| 151 |
+ options: {
|
|
| 152 |
+ browsers: ['last 1 version'] |
|
| 153 |
+ }, |
|
| 154 |
+ dist: {
|
|
| 155 |
+ files: [{
|
|
| 156 |
+ expand: true, |
|
| 157 |
+ cwd: '.tmp/styles/', |
|
| 158 |
+ src: '{,*/}*.css',
|
|
| 159 |
+ dest: '.tmp/styles/' |
|
| 160 |
+ }] |
|
| 161 |
+ } |
|
| 162 |
+ }, |
|
| 163 |
+ |
|
| 164 |
+ // Automatically inject Bower components into the app |
|
| 165 |
+ wiredep: {
|
|
| 166 |
+ app: {
|
|
| 167 |
+ src: ['<%= yeoman.app %>/index.html'], |
|
| 168 |
+ ignorePath: /\.\.\// |
|
| 169 |
+ }, |
|
| 170 |
+ sass: {
|
|
| 171 |
+ src: ['<%= yeoman.app %>/styles/{,*/}*.{scss,sass}'],
|
|
| 172 |
+ ignorePath: /(\.\.\/){1,2}bower_components\//
|
|
| 173 |
+ } |
|
| 174 |
+ }, |
|
| 175 |
+ |
|
| 176 |
+ // Compiles Sass to CSS and generates necessary files if requested |
|
| 177 |
+ compass: {
|
|
| 178 |
+ options: {
|
|
| 179 |
+ sassDir: '<%= yeoman.app %>/styles', |
|
| 180 |
+ cssDir: '.tmp/styles', |
|
| 181 |
+ generatedImagesDir: '.tmp/images/generated', |
|
| 182 |
+ imagesDir: '<%= yeoman.app %>/images', |
|
| 183 |
+ javascriptsDir: '<%= yeoman.app %>/scripts', |
|
| 184 |
+ fontsDir: '<%= yeoman.app %>/styles/fonts', |
|
| 185 |
+ importPath: './bower_components', |
|
| 186 |
+ httpImagesPath: '/images', |
|
| 187 |
+ httpGeneratedImagesPath: '/images/generated', |
|
| 188 |
+ httpFontsPath: '/styles/fonts', |
|
| 189 |
+ relativeAssets: false, |
|
| 190 |
+ assetCacheBuster: false, |
|
| 191 |
+ raw: 'Sass::Script::Number.precision = 10\n' |
|
| 192 |
+ }, |
|
| 193 |
+ dist: {
|
|
| 194 |
+ options: {
|
|
| 195 |
+ generatedImagesDir: '<%= yeoman.dist %>/images/generated' |
|
| 196 |
+ } |
|
| 197 |
+ }, |
|
| 198 |
+ server: {
|
|
| 199 |
+ options: {
|
|
| 200 |
+ debugInfo: true |
|
| 201 |
+ } |
|
| 202 |
+ } |
|
| 203 |
+ }, |
|
| 204 |
+ |
|
| 205 |
+ // Renames files for browser caching purposes |
|
| 206 |
+ filerev: {
|
|
| 207 |
+ dist: {
|
|
| 208 |
+ src: [ |
|
| 209 |
+ '<%= yeoman.dist %>/scripts/{,*/}*.js',
|
|
| 210 |
+ '<%= yeoman.dist %>/styles/{,*/}*.css',
|
|
| 211 |
+ '<%= yeoman.dist %>/images/{,*/}*.{png,jpg,jpeg,gif,webp,svg}',
|
|
| 212 |
+ '<%= yeoman.dist %>/styles/fonts/*' |
|
| 213 |
+ ] |
|
| 214 |
+ } |
|
| 215 |
+ }, |
|
| 216 |
+ |
|
| 217 |
+ // Reads HTML for usemin blocks to enable smart builds that automatically |
|
| 218 |
+ // concat, minify and revision files. Creates configurations in memory so |
|
| 219 |
+ // additional tasks can operate on them |
|
| 220 |
+ useminPrepare: {
|
|
| 221 |
+ html: '<%= yeoman.app %>/index.html', |
|
| 222 |
+ options: {
|
|
| 223 |
+ dest: '<%= yeoman.dist %>', |
|
| 224 |
+ flow: {
|
|
| 225 |
+ html: {
|
|
| 226 |
+ steps: {
|
|
| 227 |
+ js: ['concat', 'uglifyjs'], |
|
| 228 |
+ css: ['cssmin'] |
|
| 229 |
+ }, |
|
| 230 |
+ post: {}
|
|
| 231 |
+ } |
|
| 232 |
+ } |
|
| 233 |
+ } |
|
| 234 |
+ }, |
|
| 235 |
+ |
|
| 236 |
+ // Performs rewrites based on filerev and the useminPrepare configuration |
|
| 237 |
+ usemin: {
|
|
| 238 |
+ html: ['<%= yeoman.dist %>/{,*/}*.html'],
|
|
| 239 |
+ css: ['<%= yeoman.dist %>/styles/{,*/}*.css'],
|
|
| 240 |
+ options: {
|
|
| 241 |
+ assetsDirs: ['<%= yeoman.dist %>','<%= yeoman.dist %>/images'] |
|
| 242 |
+ } |
|
| 243 |
+ }, |
|
| 244 |
+ |
|
| 245 |
+ // The following *-min tasks will produce minified files in the dist folder |
|
| 246 |
+ // By default, your `index.html`'s <!-- Usemin block --> will take care of |
|
| 247 |
+ // minification. These next options are pre-configured if you do not wish |
|
| 248 |
+ // to use the Usemin blocks. |
|
| 249 |
+ // cssmin: {
|
|
| 250 |
+ // dist: {
|
|
| 251 |
+ // files: {
|
|
| 252 |
+ // '<%= yeoman.dist %>/styles/main.css': [ |
|
| 253 |
+ // '.tmp/styles/{,*/}*.css'
|
|
| 254 |
+ // ] |
|
| 255 |
+ // } |
|
| 256 |
+ // } |
|
| 257 |
+ // }, |
|
| 258 |
+ // uglify: {
|
|
| 259 |
+ // dist: {
|
|
| 260 |
+ // files: {
|
|
| 261 |
+ // '<%= yeoman.dist %>/scripts/scripts.js': [ |
|
| 262 |
+ // '<%= yeoman.dist %>/scripts/scripts.js' |
|
| 263 |
+ // ] |
|
| 264 |
+ // } |
|
| 265 |
+ // } |
|
| 266 |
+ // }, |
|
| 267 |
+ // concat: {
|
|
| 268 |
+ // dist: {}
|
|
| 269 |
+ // }, |
|
| 270 |
+ |
|
| 271 |
+ imagemin: {
|
|
| 272 |
+ dist: {
|
|
| 273 |
+ files: [{
|
|
| 274 |
+ expand: true, |
|
| 275 |
+ cwd: '<%= yeoman.app %>/images', |
|
| 276 |
+ src: '{,*/}*.{png,jpg,jpeg,gif}',
|
|
| 277 |
+ dest: '<%= yeoman.dist %>/images' |
|
| 278 |
+ }] |
|
| 279 |
+ } |
|
| 280 |
+ }, |
|
| 281 |
+ |
|
| 282 |
+ svgmin: {
|
|
| 283 |
+ dist: {
|
|
| 284 |
+ files: [{
|
|
| 285 |
+ expand: true, |
|
| 286 |
+ cwd: '<%= yeoman.app %>/images', |
|
| 287 |
+ src: '{,*/}*.svg',
|
|
| 288 |
+ dest: '<%= yeoman.dist %>/images' |
|
| 289 |
+ }] |
|
| 290 |
+ } |
|
| 291 |
+ }, |
|
| 292 |
+ |
|
| 293 |
+ htmlmin: {
|
|
| 294 |
+ dist: {
|
|
| 295 |
+ options: {
|
|
| 296 |
+ collapseWhitespace: true, |
|
| 297 |
+ conservativeCollapse: true, |
|
| 298 |
+ collapseBooleanAttributes: true, |
|
| 299 |
+ removeCommentsFromCDATA: true, |
|
| 300 |
+ removeOptionalTags: true |
|
| 301 |
+ }, |
|
| 302 |
+ files: [{
|
|
| 303 |
+ expand: true, |
|
| 304 |
+ cwd: '<%= yeoman.dist %>', |
|
| 305 |
+ src: ['*.html', 'views/{,*/}*.html'],
|
|
| 306 |
+ dest: '<%= yeoman.dist %>' |
|
| 307 |
+ }] |
|
| 308 |
+ } |
|
| 309 |
+ }, |
|
| 310 |
+ |
|
| 311 |
+ // ng-annotate tries to make the code safe for minification automatically |
|
| 312 |
+ // by using the Angular long form for dependency injection. |
|
| 313 |
+ ngAnnotate: {
|
|
| 314 |
+ dist: {
|
|
| 315 |
+ files: [{
|
|
| 316 |
+ expand: true, |
|
| 317 |
+ cwd: '.tmp/concat/scripts', |
|
| 318 |
+ src: ['*.js', '!oldieshim.js'], |
|
| 319 |
+ dest: '.tmp/concat/scripts' |
|
| 320 |
+ }] |
|
| 321 |
+ } |
|
| 322 |
+ }, |
|
| 323 |
+ |
|
| 324 |
+ // Replace Google CDN references |
|
| 325 |
+ cdnify: {
|
|
| 326 |
+ dist: {
|
|
| 327 |
+ html: ['<%= yeoman.dist %>/*.html'] |
|
| 328 |
+ } |
|
| 329 |
+ }, |
|
| 330 |
+ |
|
| 331 |
+ // Copies remaining files to places other tasks can use |
|
| 332 |
+ copy: {
|
|
| 333 |
+ dist: {
|
|
| 334 |
+ files: [{
|
|
| 335 |
+ expand: true, |
|
| 336 |
+ dot: true, |
|
| 337 |
+ cwd: '<%= yeoman.app %>', |
|
| 338 |
+ dest: '<%= yeoman.dist %>', |
|
| 339 |
+ src: [ |
|
| 340 |
+ '*.{ico,png,txt}',
|
|
| 341 |
+ '.htaccess', |
|
| 342 |
+ '*.html', |
|
| 343 |
+ 'views/{,*/}*.html',
|
|
| 344 |
+ 'images/{,*/}*.{webp}',
|
|
| 345 |
+ 'fonts/*' |
|
| 346 |
+ ] |
|
| 347 |
+ }, {
|
|
| 348 |
+ expand: true, |
|
| 349 |
+ cwd: '.tmp/images', |
|
| 350 |
+ dest: '<%= yeoman.dist %>/images', |
|
| 351 |
+ src: ['generated/*'] |
|
| 352 |
+ }, {
|
|
| 353 |
+ expand: true, |
|
| 354 |
+ cwd: '.', |
|
| 355 |
+ src: 'bower_components/bootstrap-sass-official/assets/fonts/bootstrap/*', |
|
| 356 |
+ dest: '<%= yeoman.dist %>' |
|
| 357 |
+ }] |
|
| 358 |
+ }, |
|
| 359 |
+ styles: {
|
|
| 360 |
+ expand: true, |
|
| 361 |
+ cwd: '<%= yeoman.app %>/styles', |
|
| 362 |
+ dest: '.tmp/styles/', |
|
| 363 |
+ src: '{,*/}*.css'
|
|
| 364 |
+ } |
|
| 365 |
+ }, |
|
| 366 |
+ |
|
| 367 |
+ // Run some tasks in parallel to speed up the build process |
|
| 368 |
+ concurrent: {
|
|
| 369 |
+ server: [ |
|
| 370 |
+ 'compass:server' |
|
| 371 |
+ ], |
|
| 372 |
+ test: [ |
|
| 373 |
+ 'compass' |
|
| 374 |
+ ], |
|
| 375 |
+ dist: [ |
|
| 376 |
+ 'compass:dist', |
|
| 377 |
+ 'imagemin', |
|
| 378 |
+ 'svgmin' |
|
| 379 |
+ ] |
|
| 380 |
+ }, |
|
| 381 |
+ |
|
| 382 |
+ // Test settings |
|
| 383 |
+ karma: {
|
|
| 384 |
+ unit: {
|
|
| 385 |
+ configFile: 'test/karma.conf.js', |
|
| 386 |
+ singleRun: true |
|
| 387 |
+ } |
|
| 388 |
+ }, |
|
| 389 |
+ |
|
| 390 |
+ // Settings for grunt-istanbul-coverage |
|
| 391 |
+ // NOTE: coverage task is currently not in use |
|
| 392 |
+ coverage: {
|
|
| 393 |
+ options: {
|
|
| 394 |
+ thresholds: {
|
|
| 395 |
+ 'statements': 90, |
|
| 396 |
+ 'branches': 90, |
|
| 397 |
+ 'lines': 90, |
|
| 398 |
+ 'functions': 90 |
|
| 399 |
+ }, |
|
| 400 |
+ dir: 'coverage', |
|
| 401 |
+ root: 'test' |
|
| 402 |
+ } |
|
| 403 |
+ } |
|
| 404 |
+ }); |
|
| 405 |
+ |
|
| 406 |
+ |
|
| 407 |
+ grunt.registerTask('serve', 'Compile then start a connect web server', function (target) {
|
|
| 408 |
+ if (target === 'dist') {
|
|
| 409 |
+ return grunt.task.run(['build', 'connect:dist:keepalive']); |
|
| 410 |
+ } |
|
| 411 |
+ |
|
| 412 |
+ grunt.task.run([ |
|
| 413 |
+ 'clean:server', |
|
| 414 |
+ 'wiredep', |
|
| 415 |
+ 'concurrent:server', |
|
| 416 |
+ 'autoprefixer', |
|
| 417 |
+ 'connect:livereload', |
|
| 418 |
+ 'watch' |
|
| 419 |
+ ]); |
|
| 420 |
+ }); |
|
| 421 |
+ |
|
| 422 |
+ grunt.registerTask('server', 'DEPRECATED TASK. Use the "serve" task instead', function (target) {
|
|
| 423 |
+ grunt.log.warn('The `server` task has been deprecated. Use `grunt serve` to start a server.');
|
|
| 424 |
+ grunt.task.run(['serve:' + target]); |
|
| 425 |
+ }); |
|
| 426 |
+ |
|
| 427 |
+ // Loads the coverage task which enforces the minimum coverage thresholds |
|
| 428 |
+ grunt.loadNpmTasks('grunt-istanbul-coverage');
|
|
| 429 |
+ |
|
| 430 |
+ // karma must run prior to coverage since karma will generate the coverage results |
|
| 431 |
+ grunt.registerTask('test', [
|
|
| 432 |
+ 'clean:server', |
|
| 433 |
+ 'concurrent:test', |
|
| 434 |
+ 'autoprefixer', |
|
| 435 |
+ 'connect:test', |
|
| 436 |
+ 'karma' |
|
| 437 |
+ // 'coverage' - add back if we want to enforce coverage percentages |
|
| 438 |
+ ]); |
|
| 439 |
+ |
|
| 440 |
+ grunt.registerTask('build', [
|
|
| 441 |
+ 'clean:dist', |
|
| 442 |
+ 'wiredep', |
|
| 443 |
+ 'useminPrepare', |
|
| 444 |
+ 'concurrent:dist', |
|
| 445 |
+ 'autoprefixer', |
|
| 446 |
+ 'concat', |
|
| 447 |
+ 'ngAnnotate', |
|
| 448 |
+ 'copy:dist', |
|
| 449 |
+ 'cdnify', |
|
| 450 |
+ 'cssmin', |
|
| 451 |
+ 'uglify', |
|
| 452 |
+ 'filerev', |
|
| 453 |
+ 'usemin', |
|
| 454 |
+ 'htmlmin' |
|
| 455 |
+ ]); |
|
| 456 |
+ |
|
| 457 |
+ grunt.registerTask('default', [
|
|
| 458 |
+ 'newer:jshint', |
|
| 459 |
+ 'test', |
|
| 460 |
+ 'build' |
|
| 461 |
+ ]); |
|
| 462 |
+}; |
| 0 | 463 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,41 @@ |
| 0 |
+OpenShift 3 Static Assets |
|
| 1 |
+========================= |
|
| 2 |
+The static assets for OpenShift v3. This includes the web management console. |
|
| 3 |
+ |
|
| 4 |
+Contributing |
|
| 5 |
+------------ |
|
| 6 |
+ |
|
| 7 |
+#### Getting started |
|
| 8 |
+1. Install [Nodejs](http://nodejs.org/) and [npm](https://www.npmjs.org/) |
|
| 9 |
+2. Install [grunt-cli](http://gruntjs.com/installing-grunt) and [bower](http://bower.io/) by running `npm install -g grunt-cli bower` (may need to be run with sudo) |
|
| 10 |
+3. From the `assets` directory, run the following commands: |
|
| 11 |
+ |
|
| 12 |
+ `npm install` (Install the project's dev dependencies) |
|
| 13 |
+ |
|
| 14 |
+ `bower install` (Install the project's UI dependencies) |
|
| 15 |
+ |
|
| 16 |
+ `grunt serve` (Launch the console and start watching for asset changes) |
|
| 17 |
+ |
|
| 18 |
+ Note: If you see an ENOSPC error running `grunt serve`, you may need to increase the number of files your user can watch by running this command: |
|
| 19 |
+ |
|
| 20 |
+ ``` |
|
| 21 |
+ echo fs.inotify.max_user_watches=524288 | sudo tee -a /etc/sysctl.conf && sudo sysctl -p |
|
| 22 |
+ ``` |
|
| 23 |
+ |
|
| 24 |
+#### Before opening a pull request |
|
| 25 |
+1. Run the test suite with `grunt test` |
|
| 26 |
+2. Rebase and squash changes to a single commit |
|
| 27 |
+ |
|
| 28 |
+#### Production builds |
|
| 29 |
+1. From the `assets` directory, run `grunt build` |
|
| 30 |
+2. From the root of the origin repo, run: |
|
| 31 |
+ |
|
| 32 |
+ ``` |
|
| 33 |
+ go get github.com/jteeuwen/go-bindata/... |
|
| 34 |
+ |
|
| 35 |
+ go-bindata -prefix "assets/dist" -pkg "assets" -o "pkg/assets/bindata.go" -tags "release" assets/dist/... |
|
| 36 |
+ |
|
| 37 |
+ OS_BUILD_TAGS=release hack/build-go.sh |
|
| 38 |
+ ``` |
|
| 39 |
+ |
|
| 40 |
+Now when starting the openshift all-in-one server it will also serve the console assets. The default listens at [http://localhost:8091](http://localhost:8091) |
|
| 0 | 41 |
\ No newline at end of file |
| 1 | 2 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,157 @@ |
| 0 |
+<!DOCTYPE html> |
|
| 1 |
+<html lang="en"> |
|
| 2 |
+ <head> |
|
| 3 |
+ <meta charset="utf-8"> |
|
| 4 |
+ <title>Page Not Found :(</title> |
|
| 5 |
+ <style> |
|
| 6 |
+ ::-moz-selection {
|
|
| 7 |
+ background: #b3d4fc; |
|
| 8 |
+ text-shadow: none; |
|
| 9 |
+ } |
|
| 10 |
+ |
|
| 11 |
+ ::selection {
|
|
| 12 |
+ background: #b3d4fc; |
|
| 13 |
+ text-shadow: none; |
|
| 14 |
+ } |
|
| 15 |
+ |
|
| 16 |
+ html {
|
|
| 17 |
+ padding: 30px 10px; |
|
| 18 |
+ font-size: 20px; |
|
| 19 |
+ line-height: 1.4; |
|
| 20 |
+ color: #737373; |
|
| 21 |
+ background: #f0f0f0; |
|
| 22 |
+ -webkit-text-size-adjust: 100%; |
|
| 23 |
+ -ms-text-size-adjust: 100%; |
|
| 24 |
+ } |
|
| 25 |
+ |
|
| 26 |
+ html, |
|
| 27 |
+ input {
|
|
| 28 |
+ font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; |
|
| 29 |
+ } |
|
| 30 |
+ |
|
| 31 |
+ body {
|
|
| 32 |
+ max-width: 500px; |
|
| 33 |
+ _width: 500px; |
|
| 34 |
+ padding: 30px 20px 50px; |
|
| 35 |
+ border: 1px solid #b3b3b3; |
|
| 36 |
+ border-radius: 4px; |
|
| 37 |
+ margin: 0 auto; |
|
| 38 |
+ box-shadow: 0 1px 10px #a7a7a7, inset 0 1px 0 #fff; |
|
| 39 |
+ background: #fcfcfc; |
|
| 40 |
+ } |
|
| 41 |
+ |
|
| 42 |
+ h1 {
|
|
| 43 |
+ margin: 0 10px; |
|
| 44 |
+ font-size: 50px; |
|
| 45 |
+ text-align: center; |
|
| 46 |
+ } |
|
| 47 |
+ |
|
| 48 |
+ h1 span {
|
|
| 49 |
+ color: #bbb; |
|
| 50 |
+ } |
|
| 51 |
+ |
|
| 52 |
+ h3 {
|
|
| 53 |
+ margin: 1.5em 0 0.5em; |
|
| 54 |
+ } |
|
| 55 |
+ |
|
| 56 |
+ p {
|
|
| 57 |
+ margin: 1em 0; |
|
| 58 |
+ } |
|
| 59 |
+ |
|
| 60 |
+ ul {
|
|
| 61 |
+ padding: 0 0 0 40px; |
|
| 62 |
+ margin: 1em 0; |
|
| 63 |
+ } |
|
| 64 |
+ |
|
| 65 |
+ .container {
|
|
| 66 |
+ max-width: 380px; |
|
| 67 |
+ _width: 380px; |
|
| 68 |
+ margin: 0 auto; |
|
| 69 |
+ } |
|
| 70 |
+ |
|
| 71 |
+ /* google search */ |
|
| 72 |
+ |
|
| 73 |
+ #goog-fixurl ul {
|
|
| 74 |
+ list-style: none; |
|
| 75 |
+ padding: 0; |
|
| 76 |
+ margin: 0; |
|
| 77 |
+ } |
|
| 78 |
+ |
|
| 79 |
+ #goog-fixurl form {
|
|
| 80 |
+ margin: 0; |
|
| 81 |
+ } |
|
| 82 |
+ |
|
| 83 |
+ #goog-wm-qt, |
|
| 84 |
+ #goog-wm-sb {
|
|
| 85 |
+ border: 1px solid #bbb; |
|
| 86 |
+ font-size: 16px; |
|
| 87 |
+ line-height: normal; |
|
| 88 |
+ vertical-align: top; |
|
| 89 |
+ color: #444; |
|
| 90 |
+ border-radius: 2px; |
|
| 91 |
+ } |
|
| 92 |
+ |
|
| 93 |
+ #goog-wm-qt {
|
|
| 94 |
+ width: 220px; |
|
| 95 |
+ height: 20px; |
|
| 96 |
+ padding: 5px; |
|
| 97 |
+ margin: 5px 10px 0 0; |
|
| 98 |
+ box-shadow: inset 0 1px 1px #ccc; |
|
| 99 |
+ } |
|
| 100 |
+ |
|
| 101 |
+ #goog-wm-sb {
|
|
| 102 |
+ display: inline-block; |
|
| 103 |
+ height: 32px; |
|
| 104 |
+ padding: 0 10px; |
|
| 105 |
+ margin: 5px 0 0; |
|
| 106 |
+ white-space: nowrap; |
|
| 107 |
+ cursor: pointer; |
|
| 108 |
+ background-color: #f5f5f5; |
|
| 109 |
+ background-image: -webkit-linear-gradient(rgba(255,255,255,0), #f1f1f1); |
|
| 110 |
+ background-image: -moz-linear-gradient(rgba(255,255,255,0), #f1f1f1); |
|
| 111 |
+ background-image: -ms-linear-gradient(rgba(255,255,255,0), #f1f1f1); |
|
| 112 |
+ background-image: -o-linear-gradient(rgba(255,255,255,0), #f1f1f1); |
|
| 113 |
+ -webkit-appearance: none; |
|
| 114 |
+ -moz-appearance: none; |
|
| 115 |
+ appearance: none; |
|
| 116 |
+ *overflow: visible; |
|
| 117 |
+ *display: inline; |
|
| 118 |
+ *zoom: 1; |
|
| 119 |
+ } |
|
| 120 |
+ |
|
| 121 |
+ #goog-wm-sb:hover, |
|
| 122 |
+ #goog-wm-sb:focus {
|
|
| 123 |
+ border-color: #aaa; |
|
| 124 |
+ box-shadow: 0 1px 1px rgba(0, 0, 0, 0.1); |
|
| 125 |
+ background-color: #f8f8f8; |
|
| 126 |
+ } |
|
| 127 |
+ |
|
| 128 |
+ #goog-wm-qt:hover, |
|
| 129 |
+ #goog-wm-qt:focus {
|
|
| 130 |
+ border-color: #105cb6; |
|
| 131 |
+ outline: 0; |
|
| 132 |
+ color: #222; |
|
| 133 |
+ } |
|
| 134 |
+ |
|
| 135 |
+ input::-moz-focus-inner {
|
|
| 136 |
+ padding: 0; |
|
| 137 |
+ border: 0; |
|
| 138 |
+ } |
|
| 139 |
+ </style> |
|
| 140 |
+ </head> |
|
| 141 |
+ <body> |
|
| 142 |
+ <div class="container"> |
|
| 143 |
+ <h1>Not found <span>:(</span></h1> |
|
| 144 |
+ <p>Sorry, but the page you were trying to view does not exist.</p> |
|
| 145 |
+ <p>It looks like this was the result of either:</p> |
|
| 146 |
+ <ul> |
|
| 147 |
+ <li>a mistyped address</li> |
|
| 148 |
+ <li>an out-of-date link</li> |
|
| 149 |
+ </ul> |
|
| 150 |
+ <script> |
|
| 151 |
+ var GOOG_FIXURL_LANG = (navigator.language || '').slice(0,2),GOOG_FIXURL_SITE = location.host; |
|
| 152 |
+ </script> |
|
| 153 |
+ <script src="//linkhelp.clients.google.com/tbproxy/lh/wm/fixurl.js"></script> |
|
| 154 |
+ </div> |
|
| 155 |
+ </body> |
|
| 156 |
+</html> |
| 6 | 163 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,77 @@ |
| 0 |
+<!doctype html> |
|
| 1 |
+<html class="no-js"> |
|
| 2 |
+ <head> |
|
| 3 |
+ <meta charset="utf-8"> |
|
| 4 |
+ <title>OpenShift Management Console</title> |
|
| 5 |
+ <meta name="description" content=""> |
|
| 6 |
+ <meta name="viewport" content="width=device-width"> |
|
| 7 |
+ <!-- Place favicon.ico and apple-touch-icon.png in the root directory --> |
|
| 8 |
+ <!-- build:css(.) styles/vendor.css --> |
|
| 9 |
+ <!-- bower:css --> |
|
| 10 |
+ <!-- endbower --> |
|
| 11 |
+ <!-- endbuild --> |
|
| 12 |
+ <!-- build:css(.tmp) styles/main.css --> |
|
| 13 |
+ <link rel="stylesheet" href="styles/main.css"> |
|
| 14 |
+ <!-- endbuild --> |
|
| 15 |
+ </head> |
|
| 16 |
+ <body ng-app="openshiftConsole"> |
|
| 17 |
+ <!-- Add your site or application content here --> |
|
| 18 |
+ <div class="container"> |
|
| 19 |
+ <div class="header"> |
|
| 20 |
+ <ul class="nav nav-pills pull-right"> |
|
| 21 |
+ <li class="active"><a ng-href="#">Home</a></li> |
|
| 22 |
+ <li><a ng-href="#/about">About</a></li> |
|
| 23 |
+ </ul> |
|
| 24 |
+ <h3><img src="images/openshift-logo222.png"></h3> |
|
| 25 |
+ </div> |
|
| 26 |
+ |
|
| 27 |
+ <div ng-view=""></div> |
|
| 28 |
+ |
|
| 29 |
+ <div class="footer"> |
|
| 30 |
+ <p><img src="images/redhat.png"></p> |
|
| 31 |
+ </div> |
|
| 32 |
+ </div> |
|
| 33 |
+ |
|
| 34 |
+ <!-- build:js(.) scripts/oldieshim.js --> |
|
| 35 |
+ <!--[if lt IE 9]> |
|
| 36 |
+ <script src="bower_components/es5-shim/es5-shim.js"></script> |
|
| 37 |
+ <script src="bower_components/json3/lib/json3.js"></script> |
|
| 38 |
+ <![endif]--> |
|
| 39 |
+ <!-- endbuild --> |
|
| 40 |
+ |
|
| 41 |
+ <!-- build:js(.) scripts/vendor.js --> |
|
| 42 |
+ <!-- bower:js --> |
|
| 43 |
+ <script src="bower_components/jquery/dist/jquery.js"></script> |
|
| 44 |
+ <script src="bower_components/angular/angular.js"></script> |
|
| 45 |
+ <script src="bower_components/bootstrap-sass-official/assets/javascripts/bootstrap/affix.js"></script> |
|
| 46 |
+ <script src="bower_components/bootstrap-sass-official/assets/javascripts/bootstrap/alert.js"></script> |
|
| 47 |
+ <script src="bower_components/bootstrap-sass-official/assets/javascripts/bootstrap/button.js"></script> |
|
| 48 |
+ <script src="bower_components/bootstrap-sass-official/assets/javascripts/bootstrap/carousel.js"></script> |
|
| 49 |
+ <script src="bower_components/bootstrap-sass-official/assets/javascripts/bootstrap/collapse.js"></script> |
|
| 50 |
+ <script src="bower_components/bootstrap-sass-official/assets/javascripts/bootstrap/dropdown.js"></script> |
|
| 51 |
+ <script src="bower_components/bootstrap-sass-official/assets/javascripts/bootstrap/tab.js"></script> |
|
| 52 |
+ <script src="bower_components/bootstrap-sass-official/assets/javascripts/bootstrap/transition.js"></script> |
|
| 53 |
+ <script src="bower_components/bootstrap-sass-official/assets/javascripts/bootstrap/scrollspy.js"></script> |
|
| 54 |
+ <script src="bower_components/bootstrap-sass-official/assets/javascripts/bootstrap/modal.js"></script> |
|
| 55 |
+ <script src="bower_components/bootstrap-sass-official/assets/javascripts/bootstrap/tooltip.js"></script> |
|
| 56 |
+ <script src="bower_components/bootstrap-sass-official/assets/javascripts/bootstrap/popover.js"></script> |
|
| 57 |
+ <script src="bower_components/angular-resource/angular-resource.js"></script> |
|
| 58 |
+ <script src="bower_components/angular-cookies/angular-cookies.js"></script> |
|
| 59 |
+ <script src="bower_components/angular-sanitize/angular-sanitize.js"></script> |
|
| 60 |
+ <script src="bower_components/angular-animate/angular-animate.js"></script> |
|
| 61 |
+ <script src="bower_components/angular-touch/angular-touch.js"></script> |
|
| 62 |
+ <script src="bower_components/angular-route/angular-route.js"></script> |
|
| 63 |
+ <script src="bower_components/angular-bootstrap/ui-bootstrap-tpls.js"></script> |
|
| 64 |
+ <!-- endbower --> |
|
| 65 |
+ <!-- endbuild --> |
|
| 66 |
+ |
|
| 67 |
+ <!-- build:js({.tmp,app}) scripts/scripts.js -->
|
|
| 68 |
+ <script src="scripts/app.js"></script> |
|
| 69 |
+ <script src="scripts/controllers/main.js"></script> |
|
| 70 |
+ <script src="scripts/controllers/about.js"></script> |
|
| 71 |
+ <script src="scripts/controllers/pods.js"></script> |
|
| 72 |
+ <script src="scripts/controllers/minions.js"></script> |
|
| 73 |
+ <script src="scripts/controllers/pod.js"></script> |
|
| 74 |
+ <!-- endbuild --> |
|
| 75 |
+</body> |
|
| 76 |
+</html> |
| 0 | 3 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,45 @@ |
| 0 |
+'use strict'; |
|
| 1 |
+ |
|
| 2 |
+/** |
|
| 3 |
+ * @ngdoc overview |
|
| 4 |
+ * @name openshiftConsole |
|
| 5 |
+ * @description |
|
| 6 |
+ * # openshiftConsole |
|
| 7 |
+ * |
|
| 8 |
+ * Main module of the application. |
|
| 9 |
+ */ |
|
| 10 |
+angular |
|
| 11 |
+ .module('openshiftConsole', [
|
|
| 12 |
+ 'ngAnimate', |
|
| 13 |
+ 'ngCookies', |
|
| 14 |
+ 'ngResource', |
|
| 15 |
+ 'ngRoute', |
|
| 16 |
+ 'ngSanitize', |
|
| 17 |
+ 'ngTouch' |
|
| 18 |
+ ]) |
|
| 19 |
+ .config(function ($routeProvider) {
|
|
| 20 |
+ $routeProvider |
|
| 21 |
+ .when('/', {
|
|
| 22 |
+ templateUrl: 'views/main.html', |
|
| 23 |
+ controller: 'MainCtrl' |
|
| 24 |
+ }) |
|
| 25 |
+ .when('/about', {
|
|
| 26 |
+ templateUrl: 'views/about.html', |
|
| 27 |
+ controller: 'AboutCtrl' |
|
| 28 |
+ }) |
|
| 29 |
+ .when('/pods', {
|
|
| 30 |
+ templateUrl: 'views/pods.html', |
|
| 31 |
+ controller: 'PodsController' |
|
| 32 |
+ }) |
|
| 33 |
+ .when('/pods/:pod', {
|
|
| 34 |
+ templateUrl: 'views/pod.html', |
|
| 35 |
+ controller: 'PodController' |
|
| 36 |
+ }) |
|
| 37 |
+ .when('/minions', {
|
|
| 38 |
+ templateUrl: 'views/minions.html', |
|
| 39 |
+ controller: 'MinionsController' |
|
| 40 |
+ }) |
|
| 41 |
+ .otherwise({
|
|
| 42 |
+ redirectTo: '/' |
|
| 43 |
+ }); |
|
| 44 |
+ }); |
| 0 | 45 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,17 @@ |
| 0 |
+'use strict'; |
|
| 1 |
+ |
|
| 2 |
+/** |
|
| 3 |
+ * @ngdoc function |
|
| 4 |
+ * @name openshiftConsole.controller:AboutCtrl |
|
| 5 |
+ * @description |
|
| 6 |
+ * # AboutCtrl |
|
| 7 |
+ * Controller of the openshiftConsole |
|
| 8 |
+ */ |
|
| 9 |
+angular.module('openshiftConsole')
|
|
| 10 |
+ .controller('AboutCtrl', function ($scope) {
|
|
| 11 |
+ $scope.awesomeThings = [ |
|
| 12 |
+ 'HTML5 Boilerplate', |
|
| 13 |
+ 'AngularJS', |
|
| 14 |
+ 'Karma' |
|
| 15 |
+ ]; |
|
| 16 |
+ }); |
| 0 | 17 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,17 @@ |
| 0 |
+'use strict'; |
|
| 1 |
+ |
|
| 2 |
+/** |
|
| 3 |
+ * @ngdoc function |
|
| 4 |
+ * @name openshiftConsole.controller:MainCtrl |
|
| 5 |
+ * @description |
|
| 6 |
+ * # MainCtrl |
|
| 7 |
+ * Controller of the openshiftConsole |
|
| 8 |
+ */ |
|
| 9 |
+angular.module('openshiftConsole')
|
|
| 10 |
+ .controller('MainCtrl', function ($scope) {
|
|
| 11 |
+ $scope.awesomeThings = [ |
|
| 12 |
+ 'HTML5 Boilerplate', |
|
| 13 |
+ 'AngularJS', |
|
| 14 |
+ 'Karma' |
|
| 15 |
+ ]; |
|
| 16 |
+ }); |
| 0 | 17 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,17 @@ |
| 0 |
+'use strict'; |
|
| 1 |
+ |
|
| 2 |
+/** |
|
| 3 |
+ * @ngdoc function |
|
| 4 |
+ * @name openshiftConsole.controller:AboutCtrl |
|
| 5 |
+ * @description |
|
| 6 |
+ * # AboutCtrl |
|
| 7 |
+ * Controller of the openshiftConsole |
|
| 8 |
+ */ |
|
| 9 |
+angular.module('openshiftConsole')
|
|
| 10 |
+ .controller('MinionsController', function ($scope, $http) {
|
|
| 11 |
+ $scope.minions = []; |
|
| 12 |
+ $http.defaults.useXDomain = true; |
|
| 13 |
+ $http.get('http://localhost:8080/api/v1beta1/minions').success(function(data) {
|
|
| 14 |
+ $scope.minions = data.minions; |
|
| 15 |
+ }); |
|
| 16 |
+ }); |
| 0 | 17 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,17 @@ |
| 0 |
+'use strict'; |
|
| 1 |
+ |
|
| 2 |
+/** |
|
| 3 |
+ * @ngdoc function |
|
| 4 |
+ * @name openshiftConsole.controller:AboutCtrl |
|
| 5 |
+ * @description |
|
| 6 |
+ * # AboutCtrl |
|
| 7 |
+ * Controller of the openshiftConsole |
|
| 8 |
+ */ |
|
| 9 |
+angular.module('openshiftConsole')
|
|
| 10 |
+ .controller('PodController', function ($scope, $http, $routeParams) {
|
|
| 11 |
+ $scope.pod = {desiredState: {containers: []}};
|
|
| 12 |
+ $http.defaults.useXDomain = true; |
|
| 13 |
+ $http.get('http://localhost:8080/api/v1beta1/pods/' + $routeParams.pod).success(function(data) {
|
|
| 14 |
+ $scope.pod = data; |
|
| 15 |
+ }); |
|
| 16 |
+ }); |
| 0 | 17 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,17 @@ |
| 0 |
+'use strict'; |
|
| 1 |
+ |
|
| 2 |
+/** |
|
| 3 |
+ * @ngdoc function |
|
| 4 |
+ * @name openshiftConsole.controller:AboutCtrl |
|
| 5 |
+ * @description |
|
| 6 |
+ * # AboutCtrl |
|
| 7 |
+ * Controller of the openshiftConsole |
|
| 8 |
+ */ |
|
| 9 |
+angular.module('openshiftConsole')
|
|
| 10 |
+ .controller('PodsController', function ($scope, $http) {
|
|
| 11 |
+ $scope.pods = []; |
|
| 12 |
+ $http.defaults.useXDomain = true; |
|
| 13 |
+ $http.get('http://localhost:8080/api/v1beta1/pods').success(function(data) {
|
|
| 14 |
+ $scope.pods = data.items; |
|
| 15 |
+ }); |
|
| 16 |
+ }); |
| 0 | 17 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,92 @@ |
| 0 |
+$icon-font-path: "../bower_components/bootstrap-sass-official/assets/fonts/bootstrap/"; |
|
| 1 |
+// bower:scss |
|
| 2 |
+@import "bootstrap-sass-official/assets/stylesheets/_bootstrap.scss"; |
|
| 3 |
+// endbower |
|
| 4 |
+ |
|
| 5 |
+.browsehappy {
|
|
| 6 |
+ margin: 0.2em 0; |
|
| 7 |
+ background: #ccc; |
|
| 8 |
+ color: #000; |
|
| 9 |
+ padding: 0.2em 0; |
|
| 10 |
+} |
|
| 11 |
+ |
|
| 12 |
+/* Space out content a bit */ |
|
| 13 |
+body {
|
|
| 14 |
+ padding-top: 20px; |
|
| 15 |
+ padding-bottom: 20px; |
|
| 16 |
+} |
|
| 17 |
+ |
|
| 18 |
+/* Everything but the jumbotron gets side spacing for mobile first views */ |
|
| 19 |
+.header, |
|
| 20 |
+.marketing, |
|
| 21 |
+.footer {
|
|
| 22 |
+ padding-left: 15px; |
|
| 23 |
+ padding-right: 15px; |
|
| 24 |
+} |
|
| 25 |
+ |
|
| 26 |
+/* Custom page header */ |
|
| 27 |
+.header {
|
|
| 28 |
+ border-bottom: 1px solid #e5e5e5; |
|
| 29 |
+ |
|
| 30 |
+ /* Make the masthead heading the same height as the navigation */ |
|
| 31 |
+ h3 {
|
|
| 32 |
+ margin-top: 0; |
|
| 33 |
+ margin-bottom: 0; |
|
| 34 |
+ line-height: 40px; |
|
| 35 |
+ padding-bottom: 19px; |
|
| 36 |
+ } |
|
| 37 |
+} |
|
| 38 |
+ |
|
| 39 |
+/* Custom page footer */ |
|
| 40 |
+.footer {
|
|
| 41 |
+ padding-top: 19px; |
|
| 42 |
+ color: #777; |
|
| 43 |
+ border-top: 1px solid #e5e5e5; |
|
| 44 |
+} |
|
| 45 |
+ |
|
| 46 |
+.container-narrow > hr {
|
|
| 47 |
+ margin: 30px 0; |
|
| 48 |
+} |
|
| 49 |
+ |
|
| 50 |
+/* Main marketing message and sign up button */ |
|
| 51 |
+.jumbotron {
|
|
| 52 |
+ text-align: center; |
|
| 53 |
+ border-bottom: 1px solid #e5e5e5; |
|
| 54 |
+ |
|
| 55 |
+ .btn {
|
|
| 56 |
+ font-size: 21px; |
|
| 57 |
+ padding: 14px 24px; |
|
| 58 |
+ } |
|
| 59 |
+} |
|
| 60 |
+ |
|
| 61 |
+/* Supporting marketing content */ |
|
| 62 |
+.marketing {
|
|
| 63 |
+ margin: 40px 0; |
|
| 64 |
+ |
|
| 65 |
+ p + h4 {
|
|
| 66 |
+ margin-top: 28px; |
|
| 67 |
+ } |
|
| 68 |
+} |
|
| 69 |
+ |
|
| 70 |
+/* Responsive: Portrait tablets and up */ |
|
| 71 |
+@media screen and (min-width: 768px) {
|
|
| 72 |
+ .container {
|
|
| 73 |
+ max-width: 730px; |
|
| 74 |
+ } |
|
| 75 |
+ |
|
| 76 |
+ /* Remove the padding we set earlier */ |
|
| 77 |
+ .header, |
|
| 78 |
+ .marketing, |
|
| 79 |
+ .footer {
|
|
| 80 |
+ padding-left: 0; |
|
| 81 |
+ padding-right: 0; |
|
| 82 |
+ } |
|
| 83 |
+ /* Space out the masthead */ |
|
| 84 |
+ .header {
|
|
| 85 |
+ margin-bottom: 30px; |
|
| 86 |
+ } |
|
| 87 |
+ /* Remove the bottom border on the jumbotron for visual effect */ |
|
| 88 |
+ .jumbotron {
|
|
| 89 |
+ border-bottom: 0; |
|
| 90 |
+ } |
|
| 91 |
+} |
| 0 | 7 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,16 @@ |
| 0 |
+<div class="simple-controller"> |
|
| 1 |
+ |
|
| 2 |
+ <div class="row-fluid"> |
|
| 3 |
+ <div class="span6 offset3"> |
|
| 4 |
+ <h2>OpenShift 3.x Demo</h2> |
|
| 5 |
+ </div> |
|
| 6 |
+ </div> |
|
| 7 |
+ <div class="row-fluid"> |
|
| 8 |
+ <div class="span6 offset3"> |
|
| 9 |
+ <h3>Minions:</h3> |
|
| 10 |
+ <ul> |
|
| 11 |
+ <li ng-repeat="minion in minions">{{minion.id}}</li>
|
|
| 12 |
+ </ul> |
|
| 13 |
+ </div> |
|
| 14 |
+ </div> |
|
| 15 |
+</div> |
| 0 | 16 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,18 @@ |
| 0 |
+<div class="simple-controller"> |
|
| 1 |
+ |
|
| 2 |
+ <div class="row-fluid"> |
|
| 3 |
+ <div class="span6 offset3"> |
|
| 4 |
+ <h2>OpenShift 3.x Demo</h2> |
|
| 5 |
+ </div> |
|
| 6 |
+ </div> |
|
| 7 |
+ <div class="row-fluid"> |
|
| 8 |
+ <div class="span6 offset3"> |
|
| 9 |
+ <h3>Pod: {{pod.id}}</h3>
|
|
| 10 |
+ <ul> |
|
| 11 |
+ <li ng-repeat="container in pod.desiredState.manifest.containers"> |
|
| 12 |
+ {{container.image}} - ports: <span ng-repeat="port in container.ports">{{port.hostPort}}:{{port.containerPort}}</span>
|
|
| 13 |
+ </li> |
|
| 14 |
+ </ul> |
|
| 15 |
+ </div> |
|
| 16 |
+ </div> |
|
| 17 |
+</div> |
| 0 | 18 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,23 @@ |
| 0 |
+<div class="simple-controller"> |
|
| 1 |
+ |
|
| 2 |
+ <div class="row-fluid"> |
|
| 3 |
+ <div class="span6 offset3"> |
|
| 4 |
+ <h2>OpenShift 3.x Demo</h2> |
|
| 5 |
+ </div> |
|
| 6 |
+ </div> |
|
| 7 |
+ <div class="row-fluid"> |
|
| 8 |
+ <div class="span6 offset3"> |
|
| 9 |
+ <h3>Pods:</h3> |
|
| 10 |
+ <ul> |
|
| 11 |
+ <li ng-repeat="pod in pods"> |
|
| 12 |
+ <a href="#/pods/{{pod.id}}">{{pod.id}}</a> - containers:
|
|
| 13 |
+ <ul> |
|
| 14 |
+ <li ng-repeat="container in pod.desiredState.manifest.containers"> |
|
| 15 |
+ {{container.image}} - ports: <span ng-repeat="port in container.ports">{{port.hostPort}}:{{port.containerPort}}</span>
|
|
| 16 |
+ </li> |
|
| 17 |
+ </ul> |
|
| 18 |
+ </li> |
|
| 19 |
+ </ul> |
|
| 20 |
+ </div> |
|
| 21 |
+ </div> |
|
| 22 |
+</div> |
| 0 | 23 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,22 @@ |
| 0 |
+{
|
|
| 1 |
+ "name": "assets", |
|
| 2 |
+ "version": "0.0.0", |
|
| 3 |
+ "dependencies": {
|
|
| 4 |
+ "angular": "~1.2.0", |
|
| 5 |
+ "json3": "~3.3.1", |
|
| 6 |
+ "es5-shim": "~3.1.0", |
|
| 7 |
+ "bootstrap-sass-official": "~3.2.0", |
|
| 8 |
+ "angular-resource": "~1.2.0", |
|
| 9 |
+ "angular-cookies": "~1.2.0", |
|
| 10 |
+ "angular-sanitize": "~1.2.0", |
|
| 11 |
+ "angular-animate": "~1.2.0", |
|
| 12 |
+ "angular-touch": "~1.2.0", |
|
| 13 |
+ "angular-route": "~1.2.0", |
|
| 14 |
+ "angular-bootstrap": "~0.11.0" |
|
| 15 |
+ }, |
|
| 16 |
+ "devDependencies": {
|
|
| 17 |
+ "angular-mocks": "~1.2.0", |
|
| 18 |
+ "angular-scenario": "~1.2.0" |
|
| 19 |
+ }, |
|
| 20 |
+ "appPath": "app" |
|
| 21 |
+} |
| 0 | 22 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,43 @@ |
| 0 |
+{
|
|
| 1 |
+ "name": "assets", |
|
| 2 |
+ "version": "0.0.0", |
|
| 3 |
+ "dependencies": {},
|
|
| 4 |
+ "devDependencies": {
|
|
| 5 |
+ "grunt": "~0.4.5", |
|
| 6 |
+ "grunt-autoprefixer": "^0.7.3", |
|
| 7 |
+ "grunt-concurrent": "^0.5.0", |
|
| 8 |
+ "grunt-contrib-clean": "^0.5.0", |
|
| 9 |
+ "grunt-contrib-compass": "^0.7.2", |
|
| 10 |
+ "grunt-contrib-concat": "^0.4.0", |
|
| 11 |
+ "grunt-contrib-connect": "^0.7.1", |
|
| 12 |
+ "grunt-contrib-copy": "^0.5.0", |
|
| 13 |
+ "grunt-contrib-cssmin": "^0.9.0", |
|
| 14 |
+ "grunt-contrib-htmlmin": "^0.3.0", |
|
| 15 |
+ "grunt-contrib-imagemin": "^0.8.1", |
|
| 16 |
+ "grunt-contrib-jshint": "^0.10.0", |
|
| 17 |
+ "grunt-contrib-uglify": "^0.4.0", |
|
| 18 |
+ "grunt-contrib-watch": "^0.6.1", |
|
| 19 |
+ "grunt-filerev": "^0.2.1", |
|
| 20 |
+ "grunt-google-cdn": "^0.4.0", |
|
| 21 |
+ "grunt-newer": "^0.7.0", |
|
| 22 |
+ "grunt-ng-annotate": "^0.3.0", |
|
| 23 |
+ "grunt-svgmin": "^0.4.0", |
|
| 24 |
+ "grunt-usemin": "^2.1.1", |
|
| 25 |
+ "grunt-wiredep": "^1.7.0", |
|
| 26 |
+ "jshint-stylish": "^0.2.0", |
|
| 27 |
+ "load-grunt-tasks": "^0.4.0", |
|
| 28 |
+ "time-grunt": "^0.3.1", |
|
| 29 |
+ "karma-phantomjs-launcher": "~0.1.4", |
|
| 30 |
+ "karma": "~0.12.23", |
|
| 31 |
+ "karma-jasmine": "~0.1.5", |
|
| 32 |
+ "grunt-karma": "~0.9.0", |
|
| 33 |
+ "karma-coverage": "~0.2.6", |
|
| 34 |
+ "grunt-istanbul-coverage": "0.0.5" |
|
| 35 |
+ }, |
|
| 36 |
+ "engines": {
|
|
| 37 |
+ "node": ">=0.10.0" |
|
| 38 |
+ }, |
|
| 39 |
+ "scripts": {
|
|
| 40 |
+ "test": "grunt test" |
|
| 41 |
+ } |
|
| 42 |
+} |
| 1 | 2 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,36 @@ |
| 0 |
+{
|
|
| 1 |
+ "node": true, |
|
| 2 |
+ "browser": true, |
|
| 3 |
+ "esnext": true, |
|
| 4 |
+ "bitwise": true, |
|
| 5 |
+ "camelcase": true, |
|
| 6 |
+ "curly": true, |
|
| 7 |
+ "eqeqeq": true, |
|
| 8 |
+ "immed": true, |
|
| 9 |
+ "indent": 2, |
|
| 10 |
+ "latedef": true, |
|
| 11 |
+ "newcap": true, |
|
| 12 |
+ "noarg": true, |
|
| 13 |
+ "quotmark": "single", |
|
| 14 |
+ "regexp": true, |
|
| 15 |
+ "undef": true, |
|
| 16 |
+ "unused": true, |
|
| 17 |
+ "strict": true, |
|
| 18 |
+ "trailing": true, |
|
| 19 |
+ "smarttabs": true, |
|
| 20 |
+ "globals": {
|
|
| 21 |
+ "after": false, |
|
| 22 |
+ "afterEach": false, |
|
| 23 |
+ "angular": false, |
|
| 24 |
+ "before": false, |
|
| 25 |
+ "beforeEach": false, |
|
| 26 |
+ "browser": false, |
|
| 27 |
+ "describe": false, |
|
| 28 |
+ "expect": false, |
|
| 29 |
+ "inject": false, |
|
| 30 |
+ "it": false, |
|
| 31 |
+ "jasmine": false, |
|
| 32 |
+ "spyOn": false |
|
| 33 |
+ } |
|
| 34 |
+} |
|
| 35 |
+ |
| 0 | 36 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,92 @@ |
| 0 |
+// Karma configuration |
|
| 1 |
+// http://karma-runner.github.io/0.12/config/configuration-file.html |
|
| 2 |
+// Generated on 2014-09-12 using |
|
| 3 |
+// generator-karma 0.8.3 |
|
| 4 |
+ |
|
| 5 |
+module.exports = function(config) {
|
|
| 6 |
+ 'use strict'; |
|
| 7 |
+ |
|
| 8 |
+ config.set({
|
|
| 9 |
+ // enable / disable watching file and executing tests whenever any file changes |
|
| 10 |
+ autoWatch: true, |
|
| 11 |
+ |
|
| 12 |
+ // base path, that will be used to resolve files and exclude |
|
| 13 |
+ basePath: '../', |
|
| 14 |
+ |
|
| 15 |
+ // testing framework to use (jasmine/mocha/qunit/...) |
|
| 16 |
+ frameworks: ['jasmine'], |
|
| 17 |
+ |
|
| 18 |
+ // list of files / patterns to load in the browser |
|
| 19 |
+ files: [ |
|
| 20 |
+ 'bower_components/angular/angular.js', |
|
| 21 |
+ 'bower_components/angular-mocks/angular-mocks.js', |
|
| 22 |
+ 'bower_components/angular-animate/angular-animate.js', |
|
| 23 |
+ 'bower_components/angular-cookies/angular-cookies.js', |
|
| 24 |
+ 'bower_components/angular-resource/angular-resource.js', |
|
| 25 |
+ 'bower_components/angular-route/angular-route.js', |
|
| 26 |
+ 'bower_components/angular-sanitize/angular-sanitize.js', |
|
| 27 |
+ 'bower_components/angular-touch/angular-touch.js', |
|
| 28 |
+ 'app/scripts/**/*.js', |
|
| 29 |
+ //'test/mock/**/*.js', |
|
| 30 |
+ 'test/spec/**/*.js' |
|
| 31 |
+ ], |
|
| 32 |
+ |
|
| 33 |
+ // list of files / patterns to exclude |
|
| 34 |
+ exclude: [], |
|
| 35 |
+ |
|
| 36 |
+ // web server port |
|
| 37 |
+ port: 8080, |
|
| 38 |
+ |
|
| 39 |
+ // Start these browsers, currently available: |
|
| 40 |
+ // - Chrome |
|
| 41 |
+ // - ChromeCanary |
|
| 42 |
+ // - Firefox |
|
| 43 |
+ // - Opera |
|
| 44 |
+ // - Safari (only Mac) |
|
| 45 |
+ // - PhantomJS |
|
| 46 |
+ // - IE (only Windows) |
|
| 47 |
+ browsers: [ |
|
| 48 |
+ 'PhantomJS' |
|
| 49 |
+ ], |
|
| 50 |
+ |
|
| 51 |
+ // Which plugins to enable |
|
| 52 |
+ plugins: [ |
|
| 53 |
+ 'karma-phantomjs-launcher', |
|
| 54 |
+ 'karma-jasmine', |
|
| 55 |
+ 'karma-coverage' |
|
| 56 |
+ ], |
|
| 57 |
+ |
|
| 58 |
+ // Continuous Integration mode |
|
| 59 |
+ // if true, it capture browsers, run tests and exit |
|
| 60 |
+ singleRun: false, |
|
| 61 |
+ |
|
| 62 |
+ colors: true, |
|
| 63 |
+ |
|
| 64 |
+ // level of logging |
|
| 65 |
+ // possible values: LOG_DISABLE || LOG_ERROR || LOG_WARN || LOG_INFO || LOG_DEBUG |
|
| 66 |
+ logLevel: config.LOG_INFO, |
|
| 67 |
+ |
|
| 68 |
+ // Uncomment the following lines if you are using grunt's server to run the tests |
|
| 69 |
+ // proxies: {
|
|
| 70 |
+ // '/': 'http://localhost:9000/' |
|
| 71 |
+ // }, |
|
| 72 |
+ // URL root prevent conflicts with the site root |
|
| 73 |
+ // urlRoot: '_karma_' |
|
| 74 |
+ |
|
| 75 |
+ preprocessors: {
|
|
| 76 |
+ // source files, that you wanna generate coverage for |
|
| 77 |
+ // do not include tests or libraries |
|
| 78 |
+ // (these files will be instrumented by Istanbul) |
|
| 79 |
+ 'app/**/*.js': ['coverage'] |
|
| 80 |
+ }, |
|
| 81 |
+ |
|
| 82 |
+ reporters: ['progress', 'coverage'], |
|
| 83 |
+ |
|
| 84 |
+ coverageReporter: {
|
|
| 85 |
+ reporters:[ |
|
| 86 |
+ {type: 'json', dir:'test/coverage/'},
|
|
| 87 |
+ {type: 'text-summary', dir:'test/coverage/'}
|
|
| 88 |
+ ] |
|
| 89 |
+ } |
|
| 90 |
+ }); |
|
| 91 |
+}; |
| 0 | 92 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,22 @@ |
| 0 |
+'use strict'; |
|
| 1 |
+ |
|
| 2 |
+describe('Controller: AboutCtrl', function () {
|
|
| 3 |
+ |
|
| 4 |
+ // load the controller's module |
|
| 5 |
+ beforeEach(module('openshiftConsole'));
|
|
| 6 |
+ |
|
| 7 |
+ var AboutCtrl, |
|
| 8 |
+ scope; |
|
| 9 |
+ |
|
| 10 |
+ // Initialize the controller and a mock scope |
|
| 11 |
+ beforeEach(inject(function ($controller, $rootScope) {
|
|
| 12 |
+ scope = $rootScope.$new(); |
|
| 13 |
+ AboutCtrl = $controller('AboutCtrl', {
|
|
| 14 |
+ $scope: scope |
|
| 15 |
+ }); |
|
| 16 |
+ })); |
|
| 17 |
+ |
|
| 18 |
+ it('should attach a list of awesomeThings to the scope', function () {
|
|
| 19 |
+ expect(scope.awesomeThings.length).toBe(3); |
|
| 20 |
+ }); |
|
| 21 |
+}); |
| 0 | 22 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,22 @@ |
| 0 |
+'use strict'; |
|
| 1 |
+ |
|
| 2 |
+describe('Controller: MainCtrl', function () {
|
|
| 3 |
+ |
|
| 4 |
+ // load the controller's module |
|
| 5 |
+ beforeEach(module('openshiftConsole'));
|
|
| 6 |
+ |
|
| 7 |
+ var MainCtrl, |
|
| 8 |
+ scope; |
|
| 9 |
+ |
|
| 10 |
+ // Initialize the controller and a mock scope |
|
| 11 |
+ beforeEach(inject(function ($controller, $rootScope) {
|
|
| 12 |
+ scope = $rootScope.$new(); |
|
| 13 |
+ MainCtrl = $controller('MainCtrl', {
|
|
| 14 |
+ $scope: scope |
|
| 15 |
+ }); |
|
| 16 |
+ })); |
|
| 17 |
+ |
|
| 18 |
+ it('should attach a list of awesomeThings to the scope', function () {
|
|
| 19 |
+ expect(scope.awesomeThings.length).toBe(3); |
|
| 20 |
+ }); |
|
| 21 |
+}); |
| 0 | 22 |
new file mode 100755 |
| ... | ... |
@@ -0,0 +1,11 @@ |
| 0 |
+#!/bin/bash |
|
| 1 |
+ |
|
| 2 |
+set -e |
|
| 3 |
+ |
|
| 4 |
+# If we are running inside of Travis then do not run the rest of this |
|
| 5 |
+# script unless we want to TEST_ASSETS |
|
| 6 |
+if [[ "${TRAVIS}" == "true" && "${TEST_ASSETS}" == "false" ]]; then
|
|
| 7 |
+ exit |
|
| 8 |
+fi |
|
| 9 |
+ |
|
| 10 |
+sudo apt-get install -qq ruby |
|
| 0 | 11 |
\ No newline at end of file |
| ... | ... |
@@ -28,4 +28,10 @@ for arg; do |
| 28 | 28 |
binaries+=("${OS_GO_PACKAGE}/${arg}")
|
| 29 | 29 |
done |
| 30 | 30 |
|
| 31 |
-go install -ldflags "-X github.com/GoogleCloudPlatform/kubernetes/pkg/version.gitCommit '${kube_version}' -X github.com/openshift/origin/pkg/version.commitFromGit '${version}'" "${binaries[@]}"
|
|
| 31 |
+build_tags="" |
|
| 32 |
+if [[ ! -z "$OS_BUILD_TAGS" ]]; then |
|
| 33 |
+ build_tags="-tags \"$OS_BUILD_TAGS\"" |
|
| 34 |
+fi |
|
| 35 |
+ |
|
| 36 |
+ |
|
| 37 |
+go install $build_tags -ldflags "-X github.com/GoogleCloudPlatform/kubernetes/pkg/version.gitCommit '${kube_version}' -X github.com/openshift/origin/pkg/version.commitFromGit '${version}'" "${binaries[@]}"
|
| ... | ... |
@@ -17,6 +17,8 @@ function gitcommit() {
|
| 17 | 17 |
# Check if the tree is dirty. |
| 18 | 18 |
if ! dirty_tree=$(git status --porcelain) || [[ -n "${dirty_tree}" ]]; then
|
| 19 | 19 |
echo "${git_commit}-dirty"
|
| 20 |
+ else |
|
| 21 |
+ echo "${git_commit}"
|
|
| 20 | 22 |
fi |
| 21 | 23 |
else |
| 22 | 24 |
echo "(none)" |
| ... | ... |
@@ -71,3 +73,5 @@ export GOPATH |
| 71 | 71 |
|
| 72 | 72 |
# Unset GOBIN in case it already exists in the current session. |
| 73 | 73 |
unset GOBIN |
| 74 |
+ |
|
| 75 |
+OS_BUILD_TAGS=${OS_BUILD_TAGS-}
|
|
| 74 | 76 |
\ No newline at end of file |
| 75 | 77 |
new file mode 100755 |
| ... | ... |
@@ -0,0 +1,16 @@ |
| 0 |
+#!/bin/bash |
|
| 1 |
+ |
|
| 2 |
+set -e |
|
| 3 |
+ |
|
| 4 |
+# If we are running inside of Travis then do not run the rest of this |
|
| 5 |
+# script unless we want to TEST_ASSETS |
|
| 6 |
+if [[ "${TRAVIS}" == "true" && "${TEST_ASSETS}" == "false" ]]; then
|
|
| 7 |
+ exit |
|
| 8 |
+fi |
|
| 9 |
+ |
|
| 10 |
+npm install -g bower grunt-cli |
|
| 11 |
+pushd assets > /dev/null |
|
| 12 |
+ npm install |
|
| 13 |
+ bower install |
|
| 14 |
+popd > /dev/null |
|
| 15 |
+gem install compass |
|
| 0 | 16 |
\ No newline at end of file |
| 1 | 17 |
new file mode 100755 |
| ... | ... |
@@ -0,0 +1,13 @@ |
| 0 |
+#!/bin/bash |
|
| 1 |
+ |
|
| 2 |
+set -e |
|
| 3 |
+ |
|
| 4 |
+# If we are running inside of Travis then do not run the rest of this |
|
| 5 |
+# script unless we want to TEST_ASSETS |
|
| 6 |
+if [[ "${TRAVIS}" == "true" && "${TEST_ASSETS}" == "false" ]]; then
|
|
| 7 |
+ exit |
|
| 8 |
+fi |
|
| 9 |
+ |
|
| 10 |
+pushd assets > /dev/null |
|
| 11 |
+ grunt test |
|
| 12 |
+popd > /dev/null |
|
| 0 | 13 |
\ No newline at end of file |
| 1 | 2 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,38 @@ |
| 0 |
+// +build !release |
|
| 1 |
+ |
|
| 2 |
+package assets |
|
| 3 |
+ |
|
| 4 |
+import ( |
|
| 5 |
+ "fmt" |
|
| 6 |
+) |
|
| 7 |
+ |
|
| 8 |
+// This file contains no-op versions of the methods for use during non-release builds |
|
| 9 |
+ |
|
| 10 |
+// Asset loads and returns the asset for the given name. |
|
| 11 |
+// It returns an error if the asset could not be found or |
|
| 12 |
+// could not be loaded. |
|
| 13 |
+func Asset(name string) ([]byte, error) {
|
|
| 14 |
+ return nil, fmt.Errorf("Asset %s not found", name)
|
|
| 15 |
+} |
|
| 16 |
+ |
|
| 17 |
+// AssetNames returns the names of the assets. |
|
| 18 |
+func AssetNames() []string {
|
|
| 19 |
+ return []string{}
|
|
| 20 |
+} |
|
| 21 |
+ |
|
| 22 |
+// AssetDir returns the file names below a certain |
|
| 23 |
+// directory embedded in the file by go-bindata. |
|
| 24 |
+// For example if you run go-bindata on data/... and data contains the |
|
| 25 |
+// following hierarchy: |
|
| 26 |
+// data/ |
|
| 27 |
+// foo.txt |
|
| 28 |
+// img/ |
|
| 29 |
+// a.png |
|
| 30 |
+// b.png |
|
| 31 |
+// then AssetDir("data") would return []string{"foo.txt", "img"}
|
|
| 32 |
+// AssetDir("data/img") would return []string{"a.png", "b.png"}
|
|
| 33 |
+// AssetDir("foo.txt") and AssetDir("notexist") would return an error
|
|
| 34 |
+// AssetDir("") will return []string{"data"}.
|
|
| 35 |
+func AssetDir(name string) ([]string, error) {
|
|
| 36 |
+ return []string{}, nil
|
|
| 37 |
+} |
| ... | ... |
@@ -1,6 +1,7 @@ |
| 1 | 1 |
package master |
| 2 | 2 |
|
| 3 | 3 |
import ( |
| 4 |
+ "fmt" |
|
| 4 | 5 |
"net/http" |
| 5 | 6 |
"os" |
| 6 | 7 |
"path" |
| ... | ... |
@@ -23,12 +24,14 @@ import ( |
| 23 | 23 |
etcdconfig "github.com/coreos/etcd/config" |
| 24 | 24 |
"github.com/coreos/etcd/etcd" |
| 25 | 25 |
etcdclient "github.com/coreos/go-etcd/etcd" |
| 26 |
+ "github.com/elazarl/go-bindata-assetfs" |
|
| 26 | 27 |
"github.com/golang/glog" |
| 27 | 28 |
cadvisor "github.com/google/cadvisor/client" |
| 28 | 29 |
"github.com/spf13/cobra" |
| 29 | 30 |
|
| 30 | 31 |
"github.com/openshift/origin/pkg/api/latest" |
| 31 | 32 |
"github.com/openshift/origin/pkg/api/v1beta1" |
| 33 |
+ "github.com/openshift/origin/pkg/assets" |
|
| 32 | 34 |
"github.com/openshift/origin/pkg/build" |
| 33 | 35 |
buildapi "github.com/openshift/origin/pkg/build/api" |
| 34 | 36 |
buildregistry "github.com/openshift/origin/pkg/build/registry/build" |
| ... | ... |
@@ -48,6 +51,7 @@ import ( |
| 48 | 48 |
"github.com/openshift/origin/pkg/image/registry/imagerepository" |
| 49 | 49 |
"github.com/openshift/origin/pkg/image/registry/imagerepositorymapping" |
| 50 | 50 |
"github.com/openshift/origin/pkg/template" |
| 51 |
+ "github.com/openshift/origin/pkg/version" |
|
| 51 | 52 |
|
| 52 | 53 |
// Register versioned api types |
| 53 | 54 |
_ "github.com/openshift/origin/pkg/config/api/v1beta1" |
| ... | ... |
@@ -158,6 +162,7 @@ func (c *config) getEtcdClient() (*etcdclient.Client, []string) {
|
| 158 | 158 |
func (c *config) startAllInOne() {
|
| 159 | 159 |
c.runEtcd() |
| 160 | 160 |
c.runApiserver() |
| 161 |
+ c.runAssetServer() |
|
| 161 | 162 |
c.runKubelet() |
| 162 | 163 |
c.runProxy() |
| 163 | 164 |
c.runScheduler() |
| ... | ... |
@@ -266,6 +271,38 @@ func (c *config) runApiserver() {
|
| 266 | 266 |
}, 0) |
| 267 | 267 |
} |
| 268 | 268 |
|
| 269 |
+func (c *config) runAssetServer() {
|
|
| 270 |
+ // TODO prefix should be able to be overridden at the command line |
|
| 271 |
+ // move this out to a helper / config |
|
| 272 |
+ prefix := fmt.Sprintf("/assets/%s/", version.Get().GitCommit)
|
|
| 273 |
+ // TODO configurable listen address |
|
| 274 |
+ addr := c.masterHost + ":8091" |
|
| 275 |
+ // TODO - For now redirect requests to the root to the commit-based index.html URL |
|
| 276 |
+ // Next step is to have the root page served without redirecting. May require build |
|
| 277 |
+ // changes or altering index.html while serving. |
|
| 278 |
+ mux := http.NewServeMux() |
|
| 279 |
+ mux.Handle("/", http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
|
|
| 280 |
+ urlStr := fmt.Sprintf("%sindex.html", prefix)
|
|
| 281 |
+ http.Redirect(w, req, urlStr, http.StatusTemporaryRedirect) |
|
| 282 |
+ })) |
|
| 283 |
+ |
|
| 284 |
+ mux.Handle(prefix, http.StripPrefix(prefix, http.FileServer( |
|
| 285 |
+ &assetfs.AssetFS{assets.Asset, assets.AssetDir, ""})))
|
|
| 286 |
+ |
|
| 287 |
+ osAssets := &http.Server{
|
|
| 288 |
+ Addr: addr, |
|
| 289 |
+ Handler: mux, |
|
| 290 |
+ ReadTimeout: 5 * time.Minute, |
|
| 291 |
+ WriteTimeout: 5 * time.Minute, |
|
| 292 |
+ MaxHeaderBytes: 1 << 20, |
|
| 293 |
+ } |
|
| 294 |
+ |
|
| 295 |
+ go util.Forever(func() {
|
|
| 296 |
+ glog.Infof("Started OpenShift static asset server at http://%s", addr)
|
|
| 297 |
+ glog.Fatal(osAssets.ListenAndServe()) |
|
| 298 |
+ }, 0) |
|
| 299 |
+} |
|
| 300 |
+ |
|
| 269 | 301 |
func (c *config) runKubelet() {
|
| 270 | 302 |
rootDirectory := path.Clean(c.VolumeDir) |
| 271 | 303 |
minionHost := c.bindAddr |