Browse code

Merge pull request #105 from jwforres/add_console_framework

Merged by openshift-bot

OpenShift Bot authored on 2014/09/24 03:14:20
Showing 71 changed files
... ...
@@ -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 79
new file mode 100644
... ...
@@ -0,0 +1,3 @@
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
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 36
new file mode 100644
... ...
@@ -0,0 +1 @@
0
+// sample file
0 1
new file mode 100644
... ...
@@ -0,0 +1 @@
0
+// sample file
0 1
new file mode 100644
... ...
@@ -0,0 +1 @@
0
+// sample file
0 1
new file mode 100644
... ...
@@ -0,0 +1 @@
0
+// sample file
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 184
new file mode 100644
... ...
@@ -0,0 +1,3 @@
0
+{
1
+  "directory": "bower_components"
2
+}
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 21
new file mode 100644
... ...
@@ -0,0 +1 @@
0
+* text=auto
0 1
\ No newline at end of file
1 2
new file mode 100644
... ...
@@ -0,0 +1,5 @@
0
+node_modules
1
+dist
2
+.tmp
3
+.sass-cache
4
+bower_components
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 42
new file mode 100644
... ...
@@ -0,0 +1 @@
0
+*.coffee
0 1
\ 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>
0 157
new file mode 100644
1 158
Binary files /dev/null and b/assets/app/favicon.ico differ
2 159
new file mode 100644
3 160
Binary files /dev/null and b/assets/app/images/openshift-logo222.png differ
4 161
new file mode 100644
5 162
Binary files /dev/null and b/assets/app/images/redhat.png differ
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 77
new file mode 100644
... ...
@@ -0,0 +1,3 @@
0
+# robotstxt.org
1
+
2
+User-agent: *
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 92
new file mode 100644
... ...
@@ -0,0 +1 @@
0
+<p>This is the about view.</p>
0 1
new file mode 100644
... ...
@@ -0,0 +1,7 @@
0
+<div class="jumbotron">
1
+  <p class="lead">
2
+    The v3 management console is coming soon...
3
+  </p>
4
+</div>
5
+
6
+
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
+}
0 43
new file mode 100644
... ...
@@ -0,0 +1 @@
0
+coverage
0 1
\ No newline at end of file
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 14
new file mode 100644
... ...
@@ -0,0 +1 @@
0
+bindata.go
0 1
\ 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