• Stars
    star
    127
  • Rank 282,740 (Top 6 %)
  • Language
    Go
  • License
    Apache License 2.0
  • Created over 5 years ago
  • Updated 6 months ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

A complete solution for static files in Go code

gitfs

codecov GoDoc

Package gitfs is a complete solution for static files in Go code.

When Go code uses non-Go files, they are not packaged into the binary. The common approach to the problem, as implemented by go-bindata is to convert all the required static files into Go code, which eventually compiled into the binary.

This library takes a different approach, in which the static files are not required to be "binary-packed", and even no required to be in the same repository as the Go code. This package enables loading static content from a remote git repository, or packing it to the binary if desired or loaded from local path for development process. The transition from remote repository to binary packed content, to local content is completely smooth.

The API is simple and minimalistic. The New method returns a (sub)tree of a Git repository, represented by the standard http.FileSystem interface. This object enables anything that is possible to do with a regular filesystem, such as opening a file or listing a directory. Additionally, the ./fsutil package provides enhancements over the http.FileSystem object (They can work with any object that implements the interface) such as loading Go templates in the standard way, walking over the filesystem, and applying glob patterns on a filesystem.

Supported features:

  • Loading of specific version/tag/branch.

  • For debug purposes, the files can be loaded from local path instead of the remote repository.

  • Files are loaded lazily by default or they can be preloaded if required.

  • Files can be packed to the Go binary using a command line tool.

  • This project is using the standard http.FileSystem interface.

  • In ./fsutil there are some general useful tools around the http.FileSystem interace.

Usage

To create a filesystem using the New function, provide the Git project with the pattern: github.com/<owner>/<repo>(/<path>)?(@<ref>)?. If no path is specified, the root of the project will be used. ref can be any git branch using heads/<branch name> or any git tag using tags/<tag>. If the tag is of Semver format, the tags/ prefix is not required. If no ref is specified, the default branch will be used.

In the following example, the repository github.com/x/y at tag v1.2.3 and internal path "static" is loaded:

fs, err := gitfs.New(ctx, "github.com/x/y/[email protected]")

The variable fs implements the http.FileSystem interface. Reading a file from the repository can be done using the Open method. This function accepts a path, relative to the root of the defined filesystem.

f, err := fs.Open("index.html")

The fs variable can be used in anything that accept the standard interface. For example, it can be used for serving static content using the standard library:

http.Handle("/", http.FileServer(fs))

Private Repositories

When used with private github repository, the Github API calls should be instrumented with the appropriate credentials. The credentials can be passed by providing an HTTP client.

For example, to use a Github Token from environnement variable GITHUB_TOKEN:

token := os.Getenv("GITHUB_TOKEN")
client := oauth2.NewClient(
	context.Background(),
	oauth2.StaticTokenSource(&oauth2.Token{AccessToken: token}))
fs, err := gitfs.New(ctx, "github.com/x/y", gitfs.OptClient(client))

Development

For quick development workflows, it is easier and faster to use local static content and not remote content that was pushed to a remote repository. This is enabled by the OptLocal option. To use this option only in local development and not in production system, it can be used as follow:

local := os.Getenv("LOCAL_DEBUG")
fs, err := gitfs.New(ctx, "github.com/x/y", gitfs.OptLocal(local))

In this example, we stored the value for OptLocal in an environment variable. As a result, when running the program with LOCAL_DEBUG=. local files will be used, while running without it will result in using the remote files. (the value of the environment variable should point to any directory within the github project).

Binary Packing

Using gitfs does not mean that files are required to be remotely fetched. When binary packing of the files is needed, a command line tool can pack them for you.

To get the tool run: go get github.com/posener/gitfs/cmd/gitfs.

Running the tool is by gitfs <patterns>. This generates a gitfs.go file in the current directory that contains all the used filesystems' data. This will cause all gitfs.New calls to automatically use the packed data, insted of fetching the data on runtime.

By default, a test will also be generated with the code. This test fails when the local files are modified without updating the binary content.

Use binary-packing with go generate: To generate all filesystems used by a project add //go:generate gitfs ./... in the root of the project. To generate only a specific filesystem add //go:generate gitfs $GOFILE in the file it is being used.

An interesting anecdote is that gitfs command is using itself for generating its own templates.

Excluding files

Files exclusion can be done by including only specific files using a glob pattern with OptGlob option, using the Glob options. This will affect both local loading of files, remote loading and binary packing (may reduce binary size). For example:

fs, err := gitfs.New(ctx,
	"github.com/x/y/templates",
	gitfs.OptGlob("*.gotmpl", "*/*.gotmpl"))

Sub Packages

  • bin: Package bin is a proxy to the internal/binfs.Register function.

  • cmd/gitfs: gitfs command line tool, for generating binary conetent of the used filesystems.

  • examples/godoc: An example locally serves files from github.com/golang/go/doc.

  • examples/templates: An example that shows how gitfs helps using template files with Go code smoothly.

  • fsutil: Package fsutil provides useful utility functions for http.FileSystem.

Examples

Fsutil

The ./fsutil package is a collection of useful functions that can work with any http.FileSystem implementation. For example, here we will use a function that loads go templates from the filesystem.

ctx := context.Background()

// Open a git remote repository `posener/gitfs` in path `examples/templates`.
fs, err := New(ctx, "github.com/posener/gitfs/examples/templates")
if err != nil {
    log.Fatalf("Failed initialize filesystem: %s", err)
}

// Use util function that loads all templates according to a glob pattern.
tmpls, err := fsutil.TmplParseGlob(fs, nil, "*.gotmpl")
if err != nil {
    log.Fatalf("Failed parsing templates: %s", err)
}

// Execute the template and write to stdout.
tmpls.ExecuteTemplate(os.Stdout, "tmpl1.gotmpl", "Foo")

Output:

Hello, Foo

Open

With gitfs you can open a remote git repository, and load any file, including non-go files. In this example, the README.md file of a remote repository is loaded.

ctx := context.Background()

// The load path is of the form: github.com/<owner>/<repo>(/<path>)?(@<ref>)?.
// `ref` can reference any git tag or branch. If github releases are in Semver format,
// the `tags/` prefix is not needed in the `ref` part.
fs, err := New(ctx, "github.com/kelseyhightower/[email protected]")
if err != nil {
    log.Fatalf("Failed initialize filesystem: %s", err)
}

// Open any file in the github repository, using the `Open` function. Both files
// and directory can be opened. The content is not loaded until it is actually being
// read. The content is loaded only once.
f, err := fs.Open("README.md")
if err != nil {
    log.Fatalf("Failed opening file: %s", err)
}

// Copy the content to stdout.
io.Copy(os.Stdout, f)

Output:

# helloworld

Readme created from Go doc with goreadme

More Repositories

1

complete

bash completion written in go + bash completion for go command
Go
925
star
2

goreadme

Generate readme file from Go doc. Now available as a Github action!
Go
213
star
3

goaction

Write Github actions in Go
Go
210
star
4

h2conn

HTTP2 client-server full-duplex connection
Go
129
star
5

wstest

go websocket client for unit testing of a websocket handler
Go
101
star
6

sharedsecret

Implementation of Shamir's Secret Sharing algorithm.
Go
69
star
7

tarfs

An implementation of the FileSystem interface for tar files.
Go
58
star
8

cmd

The standard library flag package with its missing features
Go
41
star
9

ctxutil

utils for Go context
Go
25
star
10

client-timing

An HTTP client for go-server-timing middleware. Enables automatic timing propagation through HTTP calls between servers.
Go
24
star
11

order

More readable and easier ordering and comparison tasks
Go
21
star
12

mock-import

A helper mocking function to mask ImportErrors
Python
17
star
13

orm

Go Typed ORM
Go
16
star
14

context

A proof of concept implementation of scoped context
Go
16
star
15

h2demo

Code examples for blog post
Go
15
star
16

script

Easily write scripts with Go. Improvements for https://github.com/bitfield/script.
Go
14
star
17

fuzzing

Easy fuzzing with go-fuzz
Go
14
star
18

eztables

iptables in web browser
Go
11
star
19

fcontext

Go Context with (pseudo) constant access-time
Go
10
star
20

auth

Painless OAuth authentication middleware
Go
8
star
21

dont

A towel, is about the most massively useful thing an interstellar hitchhiker can have
Go
6
star
22

tiler

A Go port of https://github.com/nuno-faria/tiler.
Go
6
star
23

flag

Like the flag package, but with bash completion support!
Go
5
star
24

goaction-example

Simplest goaction example
Go
5
star
25

goreadme-server

Github App for goreadme package
Go
4
star
26

formatter

A library for formatting text - indenting and line wrapping
Go
3
star
27

wsbeam

WebSocket HTTP handler that can be used to beam (broadcast) data to all connections
Go
3
star
28

contexttest

Test package for context implementations
Go
3
star
29

chrome-github-godoc

Chrome extension that replaces Github view of git commit messages with useful godoc.org synopsis
JavaScript
3
star
30

tmplt

A small wrapper around Go templates for handling simple templates
Go
2
star
31

learn

Go
2
star
32

goaction-issues-example

Goaction example for using Github APIs
Go
2
star
33

meetups

An archive of my meetup lectures
Go
1
star
34

grpcgw

Convenience comes with grpc-ecosystem/grpc-gateway
Go
1
star
35

go

Go
1
star
36

fsutil

Go
1
star
37

state-logger

A logging tool to log on state changes
Go
1
star
38

ps1

A lightweight script that sets a nice shell prompt
Shell
1
star
39

githubapp

oauth2 Github app authentication client
Go
1
star
40

autogen

Automatically generate files
Go
1
star