Skip to content

Commit 568e769

Browse files
committed
Implement the main command, git-sizer
It can compute various dimensions about a tree object in a Git repository, in a way that is robust against git bombs. For now it must be passed the path to a Git repository and one or more tree object specifications (like `HEAD^{tree}` or `HEAD:src`). That is likely to change. To avoid starting up lots of processes, we use `git cat-file --batch` to read trees. But for blobs we only need to know the size, so use `git cat-file --batch-check` for blobs. This unfortunately means that we need to keep two `git` processes running, which means paying the git startup time twice.
0 parents  commit 568e769

15 files changed

+1015
-0
lines changed

.gitignore

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
/.gopath
2+
/bin
3+
/libexec
4+
/log
5+
/repositories
6+
/vendor

Brewfile

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
brew "go"

Makefile

+75
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
ROOTDIR := $(abspath $(CURDIR))
2+
export ROOTDIR
3+
4+
GO := $(CURDIR)/script/go
5+
GOFMT := $(CURDIR)/script/gofmt
6+
7+
BIN := libexec
8+
9+
GOBIN := $(abspath $(BIN))
10+
export GOBIN
11+
12+
GOFLAGS := \
13+
--tags "static" \
14+
-ldflags "-X main.BuildVersion=$(shell git rev-parse HEAD) -X main.BuildDescribe=$(shell git describe --tags --always --dirty)"
15+
GO_CMDS := \
16+
$(BIN)/git-sizer
17+
GO_PKGS := $(shell cd .gopath/src; find github.com/github/git-sizer/ -type f -name '*.go' | xargs -n1 dirname | sort -u)
18+
SHELL_CMDS :=
19+
RUBY_CMDS :=
20+
DEPS := \
21+
github.com/stretchr/testify
22+
GO_SRCS := $(shell find src -type f -name '*.go')
23+
24+
TEST_SH_RUNNERS := 2
25+
26+
.PHONY: all
27+
all: $(GO_CMDS) $(SHELL_CMDS) $(RUBY_CMDS)
28+
29+
libexec/%: bin/% $(GO_SRCS)
30+
$(GO) install $(GOFLAGS) github.com/github/git-sizer/$*
31+
32+
.PRECIOUS: bin/%
33+
bin/%: src/shim.sh
34+
mkdir -p bin
35+
cp $< bin/$*
36+
chmod +x bin/$*
37+
38+
.PHONY: $(SHELL_CMDS)
39+
$(SHELL_CMDS): $(BIN)/%: bin/%.sh
40+
cp $< $@
41+
42+
.PHONY: $(RUBY_CMDS)
43+
$(RUBY_CMDS): $(BIN)/%: bin/%.rb
44+
cp $< $@
45+
46+
.PHONY: deps
47+
deps:
48+
$(GO) get $(DEPS)
49+
50+
.PHONY: test
51+
test: gotest shtest
52+
53+
.PHONY: gotest
54+
gotest:
55+
$(GO) test -timeout 60s $(GOFLAGS) $(GO_PKGS)
56+
57+
.PHONY: shtest
58+
shtest: libexec/git-sizer
59+
ls -1 test/test-*.sh | xargs -I % -P $(TEST_SH_RUNNERS) -n 1 $(SHELL) % --batch
60+
61+
.PHONY: gofmt
62+
gofmt:
63+
find src test -name "*.go" -print0 | xargs -0 $(GOFMT) -l -w | sed -e 's/^/Fixing /'
64+
65+
.PHONY: goimports
66+
goimports:
67+
find src -name "*.go" -print0 | xargs -0 goimports -l -w -e
68+
69+
.PHONY: govet
70+
govet:
71+
$(GO) vet $(GO_PKGS)
72+
73+
.PHONY: clean
74+
clean:
75+
rm -rf bin libexec

README.md

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# git-sizer
2+
3+
Is your Git repository busting at the seams?
4+
5+
## Getting started
6+
7+
1. Build:
8+
9+
script/bootstrap
10+
make

script/bootstrap

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
#!/bin/bash
2+
3+
set -e
4+
5+
cd $(dirname "$0")/..
6+
7+
if [[ "$(uname -s)" = "Darwin" ]]; then
8+
brew bundle
9+
fi
10+
script/ensure-go-installed
11+
12+
rm -f .gopath/src/github.com/github/git-sizer
13+
mkdir -p .gopath/src/github.com/github
14+
ln -s "$PWD/src" .gopath/src/github.com/github/git-sizer
15+
16+
make deps

script/build

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
#!/bin/bash
2+
3+
set -e
4+
5+
cd $(dirname "$0")/..
6+
7+
make

script/cibuild

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
#!/bin/bash
2+
3+
set -e
4+
5+
cd $(dirname "$0")/..
6+
7+
script/install-vendored-go
8+
script/bootstrap
9+
script/build
10+
make test

script/ensure-go-installed

+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
#!/bin/bash
2+
3+
ROOTDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )/.." && pwd )"
4+
5+
# Is go installed, and at least 1.7?
6+
go_ok() {
7+
case "$(go version 2>/dev/null | sed -n 's/.*go\([0-9][0-9]*\.[0-9][0-9]*\).*/\1/p' | head -n 1)" in
8+
""|0.*|1.[0123456])
9+
false ;;
10+
*)
11+
true ;;
12+
esac
13+
}
14+
15+
# If a local go is installed, use it.
16+
set_up_vendored_go() {
17+
GO_VERSION=go1.8.1
18+
VENDORED_GOROOT="$ROOTDIR/vendor/$GO_VERSION/go"
19+
if [ -x "$VENDORED_GOROOT/bin/go" ]; then
20+
export GOROOT="$VENDORED_GOROOT"
21+
export PATH="$GOROOT/bin:$PATH"
22+
fi
23+
}
24+
25+
set_up_vendored_go
26+
27+
if ! go_ok; then
28+
script/install-vendored-go >/dev/null || exit 1
29+
set_up_vendored_go
30+
fi

script/go

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
#!/bin/bash
2+
3+
set -e
4+
5+
export ROOTDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )/.." && pwd )"
6+
. $ROOTDIR/script/ensure-go-installed
7+
export GOPATH=$ROOTDIR/.gopath
8+
9+
exec "$(basename $0)" "$@"

script/gofmt

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
go

script/install-vendored-go

+53
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
#!/bin/bash
2+
3+
GO_VERSION=go1.8.1
4+
5+
if [ $(uname -s) = "Darwin" ]; then
6+
GO_PKG=${GO_VERSION}.darwin-amd64.tar.gz
7+
GO_PKG_SHA=25b026fe2f4de7c80b227f69588b06b93787f5b5f134fbf2d652926c08c04bcd
8+
else
9+
GO_PKG=${GO_VERSION}.linux-amd64.tar.gz
10+
GO_PKG_SHA=a579ab19d5237e263254f1eac5352efcf1d70b9dacadb6d6bb12b0911ede8994
11+
fi
12+
13+
archivesum() {
14+
shasum -a256 "$ARCHIVE"
15+
}
16+
17+
archiveok() {
18+
test -f "$ARCHIVE" && archivesum | grep -q $GO_PKG_SHA
19+
}
20+
21+
if go version 2>/dev/null | grep -q $GO_VERSION; then
22+
go version
23+
exit 0
24+
fi
25+
26+
ROOTDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )/.." && pwd )"
27+
VENDORDIR="$ROOTDIR/vendor"
28+
DOWNLOAD_URL=https://storage.googleapis.com/golang/$GO_PKG
29+
ARCHIVE="$VENDORDIR/$GO_PKG"
30+
INSTALLDIR="$VENDORDIR/$GO_VERSION"
31+
export GOROOT="$INSTALLDIR/go"
32+
INSTALLEDGO="$GOROOT/bin/go"
33+
34+
if [ -x $INSTALLEDGO ]; then
35+
"$INSTALLEDGO" version
36+
exit 0
37+
fi
38+
39+
if ! archiveok; then
40+
echo "Downloading $DOWNLOAD_URL"
41+
mkdir -p "$VENDORDIR"
42+
curl -L -o "$ARCHIVE" $DOWNLOAD_URL
43+
if ! archiveok; then
44+
archivesum 1>&2
45+
echo expected checksum $GO_PKG_SHA 1>&2
46+
exit 1
47+
fi
48+
fi
49+
50+
rm -rf "$INSTALLDIR"
51+
mkdir -p "$INSTALLDIR"
52+
tar xf "$ARCHIVE" -C "$INSTALLDIR"
53+
"$INSTALLEDGO" version

script/vendor

+58
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
#!/bin/bash
2+
3+
set -e
4+
5+
cd "$(dirname "$0")/.."
6+
7+
clone_url() {
8+
local cloneUrl=$(git config remote.origin.url)
9+
10+
if [[ "$cloneUrl" == "https://github.com/"* ]]; then
11+
echo "https://github.com/$1.git"
12+
elif [[ "$cloneUrl" == "[email protected]:"* ]]; then
13+
echo "[email protected]:$1.git"
14+
elif [ "$(uname -s)" = "Darwin" ]; then
15+
echo "https://github.com/$1.git"
16+
else
17+
echo "[email protected]:$1.git"
18+
fi
19+
}
20+
21+
ROOTDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )/.." && pwd )"
22+
SUBPROJECT=$1
23+
SUBPROJECT_VENDOR="$ROOTDIR/.gopath/src/github.com/$SUBPROJECT"
24+
SUBPROJECT_REPO="$SUBPROJECT"
25+
SUBPROJECT_GIT_URL="$(clone_url $SUBPROJECT_REPO)"
26+
SUBPROJECT_VERSION_CONFIG="$ROOTDIR/config/versions/$SUBPROJECT"
27+
28+
if [ $# -gt 1 ]; then
29+
SUBPROJECT_VERSION="$2"
30+
elif [ -f "$SUBPROJECT_VERSION_CONFIG" ]; then
31+
SUBPROJECT_VERSION="$(cat $SUBPROJECT_VERSION_CONFIG)"
32+
else
33+
printf '\e[31m' >&2
34+
echo "ERROR: No $SUBPROJECT project is configured."
35+
printf '\e[0m' >&2
36+
exit 1
37+
fi
38+
39+
if ! [ -d "$SUBPROJECT_VENDOR" ]; then
40+
mkdir -p "$SUBPROJECT_VENDOR"
41+
fi
42+
cd "$SUBPROJECT_VENDOR"
43+
44+
if [ "$(git rev-parse --verify HEAD 2>/dev/null)" = "$SUBPROJECT_VERSION" ]; then
45+
echo "$SUBPROJECT build $(echo $SUBPROJECT_VERSION | cut -c1-10) is up-to-date."
46+
else
47+
if ! [ -d ".git" ]; then
48+
git init
49+
fi
50+
if ! git config --local remote.origin.url >/dev/null; then
51+
git remote add origin "$SUBPROJECT_GIT_URL"
52+
fi
53+
git fetch origin --prune
54+
git reset --hard "$SUBPROJECT_VERSION"
55+
56+
mkdir -p "$(dirname "$SUBPROJECT_VERSION_CONFIG")"
57+
git rev-parse --verify HEAD > "$SUBPROJECT_VERSION_CONFIG"
58+
fi

0 commit comments

Comments
 (0)