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)