github.com/posener/gitfs@v1.2.2-0.20200410105819-ea4e48d73ab9/README.md (about) 1 # gitfs 2 3 [![codecov](https://codecov.io/gh/posener/gitfs/branch/master/graph/badge.svg)](https://codecov.io/gh/posener/gitfs) 4 [![GoDoc](https://img.shields.io/badge/pkg.go.dev-doc-blue)](http://pkg.go.dev/github.com/posener/gitfs) 5 6 Package gitfs is a complete solution for static files in Go code. 7 8 When Go code uses non-Go files, they are not packaged into the binary. 9 The common approach to the problem, as implemented by 10 [go-bindata](https://github.com/kevinburke/go-bindata) 11 is to convert all the required static files into Go code, which 12 eventually compiled into the binary. 13 14 This library takes a different approach, in which the static files are not 15 required to be "binary-packed", and even no required to be in the same repository 16 as the Go code. This package enables loading static content from a remote 17 git repository, or packing it to the binary if desired or loaded 18 from local path for development process. The transition from remote repository 19 to binary packed content, to local content is completely smooth. 20 21 *The API is simple and minimalistic*. The `New` method returns a (sub)tree 22 of a Git repository, represented by the standard `http.FileSystem` interface. 23 This object enables anything that is possible to do with a regular filesystem, 24 such as opening a file or listing a directory. 25 Additionally, the [./fsutil](./fsutil) package provides enhancements over the `http.FileSystem` 26 object (They can work with any object that implements the interface) such 27 as loading Go templates in the standard way, walking over the filesystem, 28 and applying glob patterns on a filesystem. 29 30 Supported features: 31 32 * Loading of specific version/tag/branch. 33 34 * For debug purposes, the files can be loaded from local path instead of the 35 remote repository. 36 37 * Files are loaded lazily by default or they can be preloaded if required. 38 39 * Files can be packed to the Go binary using a command line tool. 40 41 * This project is using the standard `http.FileSystem` interface. 42 43 * In [./fsutil](./fsutil) there are some general useful tools around the 44 `http.FileSystem` interace. 45 46 ## Usage 47 48 To create a filesystem using the `New` function, provide the Git 49 project with the pattern: `github.com/<owner>/<repo>(/<path>)?(@<ref>)?`. 50 If no `path` is specified, the root of the project will be used. 51 `ref` can be any git branch using `heads/<branch name>` or any 52 git tag using `tags/<tag>`. If the tag is of Semver format, the `tags/` 53 prefix is not required. If no `ref` is specified, the default branch will 54 be used. 55 56 In the following example, the repository `github.com/x/y` at tag v1.2.3 57 and internal path "static" is loaded: 58 59 ```go 60 fs, err := gitfs.New(ctx, "github.com/x/y/static@v1.2.3") 61 ``` 62 63 The variable `fs` implements the `http.FileSystem` interface. 64 Reading a file from the repository can be done using the `Open` method. 65 This function accepts a path, relative to the root of the defined 66 filesystem. 67 68 ```go 69 f, err := fs.Open("index.html") 70 ``` 71 72 The `fs` variable can be used in anything that accept the standard interface. 73 For example, it can be used for serving static content using the standard 74 library: 75 76 ```go 77 http.Handle("/", http.FileServer(fs)) 78 ``` 79 80 ## Private Repositories 81 82 When used with private github repository, the Github API calls should be 83 instrumented with the appropriate credentials. The credentials can be 84 passed by providing an HTTP client. 85 86 For example, to use a Github Token from environnement variable `GITHUB_TOKEN`: 87 88 ```go 89 token := os.Getenv("GITHUB_TOKEN") 90 client := oauth2.NewClient( 91 context.Background(), 92 oauth2.StaticTokenSource(&oauth2.Token{AccessToken: token})) 93 fs, err := gitfs.New(ctx, "github.com/x/y", gitfs.OptClient(client)) 94 ``` 95 96 ## Development 97 98 For quick development workflows, it is easier and faster to use local static 99 content and not remote content that was pushed to a remote repository. 100 This is enabled by the `OptLocal` option. To use this option only in 101 local development and not in production system, it can be used as follow: 102 103 ```go 104 local := os.Getenv("LOCAL_DEBUG") 105 fs, err := gitfs.New(ctx, "github.com/x/y", gitfs.OptLocal(local)) 106 ``` 107 108 In this example, we stored the value for `OptLocal` in an environment 109 variable. As a result, when running the program with `LOCAL_DEBUG=.` 110 local files will be used, while running without it will result in using 111 the remote files. (the value of the environment variable should point 112 to any directory within the github project). 113 114 ## Binary Packing 115 116 Using gitfs does not mean that files are required to be remotely fetched. 117 When binary packing of the files is needed, a command line tool can pack 118 them for you. 119 120 To get the tool run: `go get github.com/posener/gitfs/cmd/gitfs`. 121 122 Running the tool is by `gitfs <patterns>`. This generates a `gitfs.go` 123 file in the current directory that contains all the used filesystems' data. 124 This will cause all `gitfs.New` calls to automatically use the packed data, 125 insted of fetching the data on runtime. 126 127 By default, a test will also be generated with the code. This test fails 128 when the local files are modified without updating the binary content. 129 130 Use binary-packing with `go generate`: To generate all filesystems used 131 by a project add `//go:generate gitfs ./...` in the root of the project. 132 To generate only a specific filesystem add `//go:generate gitfs $GOFILE` in 133 the file it is being used. 134 135 An interesting anecdote is that gitfs command is using itself for generating 136 its own templates. 137 138 ## Excluding files 139 140 Files exclusion can be done by including only specific files using a glob 141 pattern with `OptGlob` option, using the Glob options. This will affect 142 both local loading of files, remote loading and binary packing (may 143 reduce binary size). For example: 144 145 ```go 146 fs, err := gitfs.New(ctx, 147 "github.com/x/y/templates", 148 gitfs.OptGlob("*.gotmpl", "*/*.gotmpl")) 149 ``` 150 151 ## Sub Packages 152 153 * [bin](./bin): Package bin is a proxy to the internal/binfs.Register function. 154 155 * [cmd/gitfs](./cmd/gitfs): gitfs command line tool, for generating binary conetent of the used filesystems. 156 157 * [examples/godoc](./examples/godoc): An example locally serves files from github.com/golang/go/doc. 158 159 * [examples/templates](./examples/templates): An example that shows how gitfs helps using template files with Go code smoothly. 160 161 * [fsutil](./fsutil): Package fsutil provides useful utility functions for http.FileSystem. 162 163 ## Examples 164 165 ### Fsutil 166 167 The [./fsutil](./fsutil) package is a collection of useful functions that can work with 168 any `http.FileSystem` implementation. 169 For example, here we will use a function that loads go templates from the 170 filesystem. 171 172 ```golang 173 ctx := context.Background() 174 175 // Open a git remote repository `posener/gitfs` in path `examples/templates`. 176 fs, err := New(ctx, "github.com/posener/gitfs/examples/templates") 177 if err != nil { 178 log.Fatalf("Failed initialize filesystem: %s", err) 179 } 180 181 // Use util function that loads all templates according to a glob pattern. 182 tmpls, err := fsutil.TmplParseGlob(fs, nil, "*.gotmpl") 183 if err != nil { 184 log.Fatalf("Failed parsing templates: %s", err) 185 } 186 187 // Execute the template and write to stdout. 188 tmpls.ExecuteTemplate(os.Stdout, "tmpl1.gotmpl", "Foo") 189 ``` 190 191 Output: 192 193 ``` 194 Hello, Foo 195 ``` 196 197 ### Open 198 199 With gitfs you can open a remote git repository, and load any file, 200 including non-go files. 201 In this example, the README.md file of a remote repository is loaded. 202 203 ```golang 204 ctx := context.Background() 205 206 // The load path is of the form: github.com/<owner>/<repo>(/<path>)?(@<ref>)?. 207 // `ref` can reference any git tag or branch. If github releases are in Semver format, 208 // the `tags/` prefix is not needed in the `ref` part. 209 fs, err := New(ctx, "github.com/kelseyhightower/helloworld@3.0.0") 210 if err != nil { 211 log.Fatalf("Failed initialize filesystem: %s", err) 212 } 213 214 // Open any file in the github repository, using the `Open` function. Both files 215 // and directory can be opened. The content is not loaded until it is actually being 216 // read. The content is loaded only once. 217 f, err := fs.Open("README.md") 218 if err != nil { 219 log.Fatalf("Failed opening file: %s", err) 220 } 221 222 // Copy the content to stdout. 223 io.Copy(os.Stdout, f) 224 ``` 225 226 Output: 227 228 ``` 229 # helloworld 230 ``` 231 232 --- 233 Readme created from Go doc with [goreadme](https://github.com/posener/goreadme)