Skip to content

Commit

Permalink
WIP - gitserver, a fast, simple way to run Git
Browse files Browse the repository at this point in the history
  • Loading branch information
smarterclayton committed Apr 27, 2015
1 parent 962468f commit 8954b46
Show file tree
Hide file tree
Showing 15 changed files with 1,143 additions and 67 deletions.
13 changes: 13 additions & 0 deletions examples/gitserver/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
Configurable git Server
=======================

This example provides automatic mirroring of Git repositories, intended
for use within a container or Kubernetes pod. It can clone repositories
from remote systems on startup as well as remotely register hooks. It
can automatically initialize and receive Git directories on push.

In the more advanced modes, it can integrate with an OpenShift server to
automatically perform actions when new repositories are created, like
reading the build configs in the current namespace and performing
automatic mirroring of their input, and creating new build-configs when
content is pushed.
48 changes: 48 additions & 0 deletions examples/gitserver/hooks/detect-language
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
#!/bin/bash
#
# detect-language returns a string indicating the image repository to use as a base
# image for this source repository. Return "docker.io/*/*" for Docker images, a two
# segment entry for a local image repository, or a single segment name to search
# in the current namespace. Set a tag to qualify the version - e.g. "ruby:1.9.3",
# "nodejs:0.10".
#

set -o errexit
set -o nounset
set -o pipefail

function has {
[[ -n $(git ls-tree --full-name --name-only HEAD ${@:1}) ]]
}
function key {
git config --local --get "${1}"
}

prefix=${PREFIX:-openshift/}

if has Gemfile; then
echo "${prefix}ruby"
exit 0
fi

if has requirements.txt; then
echo "${prefix}python"
exit 0
fi

if has package.json app.json; then
echo "${prefix}nodejs"
exit 0
fi

if has '*.go'; then
echo "${prefix}golang"
exit 0
fi

if has index.php; then
echo "${prefix}php"
exit 0
fi

exit 1
37 changes: 37 additions & 0 deletions examples/gitserver/hooks/post-receive
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
#!/bin/bash

set -o errexit
set -o nounset
set -o pipefail

function key {
git config --local --get "${1}"
}
function addkey {
git config --local --add "${1}" "${2}"
}

function detect {
if detected=$(key openshift.io.detect); then
exit 0
fi
if ! url=$(key gitserver.self.url); then
echo "detect: no self url set"
exit 0
fi
if ! lang=$($(dirname $0)/detect-language); then
exit 0
fi
echo "detect: found language ${lang}"

if ! osc=$(which osc); then
echo "detect: osc is not installed"
addkey openshift.io.detect 1
exit 0
fi
osc new-app "${lang}~${url}"
addkey openshift.io.detect 1
}

detect

25 changes: 25 additions & 0 deletions examples/gitserver/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// +build !openshift

package main

import (
"fmt"
"log"
"os"

"github.com/openshift/origin/pkg/gitserver"
)

func main() {
if len(os.Args) != 1 {
fmt.Printf(`git-server - Expose Git repositories to the network
%[1]s`, gitserver.EnvironmentHelp)
os.Exit(0)
}
config, err := gitserver.NewEnviromentConfig()
if err != nil {
log.Fatal(err)
}
log.Fatal(gitserver.Start(config))
}
43 changes: 43 additions & 0 deletions examples/gitserver/main_openshift.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
// +build openshift

package main

import (
"fmt"
"log"
"net/url"
"os"

"github.com/openshift/origin/pkg/gitserver"
"github.com/openshift/origin/pkg/gitserver/autobuild"
)

func main() {
if len(os.Args) != 1 {
fmt.Printf(`git-server - Expose Git repositories to the network
%[1]s`, gitserver.EnvironmentHelp)
os.Exit(0)
}
config, err := gitserver.NewEnviromentConfig()
if err != nil {
log.Fatal(err)
}
link, err := autobuild.NewAutoLinkBuildsFromEnvironment()
switch {
case err == autobuild.ErrNotEnabled:
case err != nil:
log.Fatal(err)
default:
link.LinkFn = func(name string) *url.URL { return gitserver.RepositoryURL(config, name, nil) }
clones, err := link.Link()
if err != nil {
log.Printf("error: %v", err)
break
}
for name, v := range clones {
config.InitialClones[name] = v
}
}
log.Fatal(gitserver.Start(config))
}
13 changes: 4 additions & 9 deletions pkg/generate/app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import (
"fmt"
"net"
"net/url"
"path"
"reflect"
"strconv"
"strings"
Expand All @@ -19,6 +18,7 @@ import (

buildapi "github.com/openshift/origin/pkg/build/api"
deployapi "github.com/openshift/origin/pkg/deploy/api"
"github.com/openshift/origin/pkg/generate/git"
imageapi "github.com/openshift/origin/pkg/image/api"
)

Expand Down Expand Up @@ -70,15 +70,10 @@ func (g *Generated) WithType(slicePtr interface{}) bool {

func nameFromGitURL(url *url.URL) (string, bool) {
// from path
if len(url.Path) > 0 {
base := path.Base(url.Path)
if len(base) > 0 && base != "/" {
if ext := path.Ext(base); ext == ".git" {
base = base[:len(base)-4]
}
return base, true
}
if name, ok := git.NameFromRepositoryURL(url); ok {
return name, true
}
// TODO: path is questionable
if len(url.Host) > 0 {
// from host with port
if host, _, err := net.SplitHostPort(url.Host); err == nil {
Expand Down
40 changes: 3 additions & 37 deletions pkg/generate/app/sourcelookup.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,7 @@ import (
"io/ioutil"
"net/url"
"os"
"path/filepath"
"regexp"
"strings"

"github.com/openshift/origin/pkg/generate/dockerfile"
"github.com/openshift/origin/pkg/generate/git"
Expand Down Expand Up @@ -42,41 +40,9 @@ type SourceRepository struct {
// NewSourceRepository creates a reference to a local or remote source code repository from
// a URL or path.
func NewSourceRepository(s string) (*SourceRepository, error) {
var location *url.URL
switch {
case strings.HasPrefix(s, "git@"):
base := "git://" + strings.TrimPrefix(s, "git@")
url, err := url.Parse(base)
if err != nil {
return nil, err
}
location = url

default:
uri, err := url.Parse(s)
if err != nil {
return nil, err
}

if uri.Scheme == "" {
path := s
ref := ""
segments := strings.SplitN(path, "#", 2)
if len(segments) == 2 {
path, ref = segments[0], segments[1]
}
path, err := filepath.Abs(path)
if err != nil {
return nil, err
}
uri = &url.URL{
Scheme: "file",
Path: path,
Fragment: ref,
}
}

location = uri
location, err := git.ParseRepository(s)
if err != nil {
return nil, err
}
return &SourceRepository{
location: s,
Expand Down
8 changes: 8 additions & 0 deletions pkg/generate/generator/test/fakegit.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,11 @@ func (g *FakeGit) Checkout(dir string, ref string) error {
g.CheckoutCalled = true
return nil
}

func (g *FakeGit) CloneMirror(source, target string) error {
return nil
}

func (f *FakeGit) Fetch(source string) error {
return nil
}
69 changes: 69 additions & 0 deletions pkg/generate/git/git.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package git

import (
"net/url"
"path"
"path/filepath"
"strings"
)

// ParseRepository parses a string that may be in the Git format (git@) or URL format
// and extracts the appropriate value. Any fragment on the URL is preserved.
//
// Protocols returned:
// - http, https
// - file
// - git
func ParseRepository(s string) (*url.URL, error) {
switch {
case strings.HasPrefix(s, "git@"):
base := "git://" + strings.TrimPrefix(s, "git@")
url, err := url.Parse(base)
if err != nil {
return nil, err
}
return url, nil

default:
uri, err := url.Parse(s)
if err != nil {
return nil, err
}

if uri.Scheme == "" {
path := s
ref := ""
segments := strings.SplitN(path, "#", 2)
if len(segments) == 2 {
path, ref = segments[0], segments[1]
}
path, err := filepath.Abs(path)
if err != nil {
return nil, err
}
uri = &url.URL{
Scheme: "file",
Path: path,
Fragment: ref,
}
}

return uri, nil
}
}

// NameFromRepositoryURL suggests a name for a repository URL based on the last
// segment of the path, or returns false
func NameFromRepositoryURL(url *url.URL) (string, bool) {
// from path
if len(url.Path) > 0 {
base := path.Base(url.Path)
if len(base) > 0 && base != "/" {
if ext := path.Ext(base); ext == ".git" {
base = base[:len(base)-4]
}
return base, true
}
}
return "", false
}
Loading

0 comments on commit 8954b46

Please sign in to comment.