mirrorcat

package module
v0.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Dec 21, 2017 License: MIT Imports: 11 Imported by: 1

README

This image was created by Ashley McNamara. You can find this image, and many others like it, at https://github.com/ashleymcnamara/gophers

GoDoc

MirrorCat

Tired of manually keeping branches up-to-date with one another across repositories? Are Git Hooks not enough for you for some reason? Deploy your instance of MirrorCat to expose a web service which will push your commits around to where they are needed.

Contribute

Conduct

If you would like to become an active contributor to this project please follow the instructions provided in Microsoft Azure Projects Contribution Guidelines.

This project has adopted the Microsoft Open Source Code of Conduct. For more information see the Code of Conduct FAQ or contact opencode@microsoft.com with any additional questions or comments.

Requirements

You'll need the following tools to build and test MirrorCat:

The easiest way to get a hold of MirrorCat's source is using go get:

go get -d -t github.com/Azure/mirrorcat
Running Tests

Once you've acquired the source, you can run MirrorCat's tests with the following command:

go test -race -cover -v github.com/Azure/mirrorcat/...

Documentation

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func NormalizeRef

func NormalizeRef(ref string) string

NormalizeRef removes metadata about the reference that was passed to us, and returns just it's name. Chiefly, this removes data about which repository the references belongs to, remote or local.

Example
package main

import (
	"fmt"

	"github.com/Azure/mirrorcat"
)

func main() {
	fmt.Println(mirrorcat.NormalizeRef("myBranch"))
	fmt.Println(mirrorcat.NormalizeRef("remotes/origin/myBranch"))
	fmt.Println(mirrorcat.NormalizeRef("refs/heads/myBranch"))
}
Output:

myBranch
myBranch
myBranch

func Push

func Push(ctx context.Context, original, mirror RemoteRef, depth int) (err error)

Push clones the original repository, then pushes the branch specified to another repository.

Types

type CmdErr

type CmdErr struct {
	Output []byte
	// contains filtered or unexported fields
}

CmdErr allows the Output of a completed CMD to be included with the error itself. This is useful for capturing Failure messages communicated through /dev/stderr

func (CmdErr) Error

func (ce CmdErr) Error() string

type Commit

type Commit struct {
	ID      string   `json:"id"`
	Message string   `json:"message"`
	Author  Identity `json:"author"`
	URL     string   `json:"url"`
}

Commit is an item detailed in the PushEvent page linked above, which contains metadata about commits that were pushed and that we're being informed of by a webhook.

type DefaultMirrorFinder

type DefaultMirrorFinder struct {
	sync.RWMutex
	// contains filtered or unexported fields
}

DefaultMirrorFinder provides an in-memory location for storing information about which branches should mirror which others.

Note: This is most powerful if combined with github.com/spf13/viper and its Watch

functionality
Example
package main

import (
	"context"
	"fmt"
	"time"

	"github.com/Azure/mirrorcat"
)

func main() {
	original := mirrorcat.RemoteRef{
		Repository: "https://github.com/Azure/mirrorcat",
		Ref:        "master",
	}

	mirrors := []mirrorcat.RemoteRef{
		{
			Repository: "https://github.com/marstr/mirrorcat",
			Ref:        "master",
		},
		{
			Repository: "https://github.com/haydenmc/mirrorcat",
			Ref:        "master",
		},
	}

	subject := mirrorcat.NewDefaultMirrorFinder()
	subject.AddMirrors(original, mirrors...)

	results := make(chan mirrorcat.RemoteRef)

	ctx, cancel := context.WithTimeout(context.Background(), 500*time.Millisecond)
	defer cancel()

	go subject.FindMirrors(ctx, original, results)

loop:
	for {
		select {
		case entry, ok := <-results:
			if ok {
				fmt.Println(entry.Repository, entry.Ref)
			} else {
				break loop
			}
		case <-ctx.Done():
			break loop
		}
	}

}
Output:

https://github.com/marstr/mirrorcat master
https://github.com/haydenmc/mirrorcat master

func NewDefaultMirrorFinder

func NewDefaultMirrorFinder() *DefaultMirrorFinder

NewDefaultMirrorFinder creates an empty instance of a MirrorFinder

func (*DefaultMirrorFinder) AddMirrors

func (dmf *DefaultMirrorFinder) AddMirrors(original RemoteRef, branches ...RemoteRef)

AddMirrors registers a new remote and branch that should be cloned whenever

func (*DefaultMirrorFinder) ClearAll

func (dmf *DefaultMirrorFinder) ClearAll()

ClearAll removes all associations between References

func (*DefaultMirrorFinder) ClearMirrors

func (dmf *DefaultMirrorFinder) ClearMirrors(original RemoteRef)

ClearMirrors removes the association between a particular `RemoteRef` and all mirrored copies.

func (*DefaultMirrorFinder) FindMirrors

func (dmf *DefaultMirrorFinder) FindMirrors(ctx context.Context, original RemoteRef, results chan<- RemoteRef) error

FindMirrors iterates through the entries that had been added and publishes them all to `results` See Also: AddMirror(url.URL, branches ...string)

type Identity

type Identity struct {
	Name     string `json:"name"`
	Email    string `json:"email"`
	Username string `json:"username"`
}

Identity holds metadata about a GitHub Author

type MergeFinder

type MergeFinder []MirrorFinder

MergeFinder allows a mechanism to find mirror mappings from multiple underlying MirrorFinders.

func (MergeFinder) FindMirrors

func (haystack MergeFinder) FindMirrors(ctx context.Context, needle RemoteRef, results chan<- RemoteRef) (err error)

FindMirrors enumerates each MirrorFinder, and

Example
package main

import (
	"context"
	"fmt"
	"time"

	"github.com/Azure/mirrorcat"
)

func main() {
	ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
	defer cancel()

	const mainRepo = "github.com/Azure/mirrorcat"
	const secondaryRepo = "github.com/marstr/mirrorcat"

	child1, child2 := mirrorcat.NewDefaultMirrorFinder(), mirrorcat.NewDefaultMirrorFinder()

	orig := mirrorcat.RemoteRef{Repository: mainRepo, Ref: "master"}

	child1.AddMirrors(orig, mirrorcat.RemoteRef{Repository: secondaryRepo, Ref: "master"})
	child2.AddMirrors(orig, mirrorcat.RemoteRef{Repository: mainRepo, Ref: "dev"})

	subject := mirrorcat.MergeFinder([]mirrorcat.MirrorFinder{child1, child2})

	results, errs := make(chan mirrorcat.RemoteRef), make(chan error, 1)

	go func() {
		select {
		case errs <- subject.FindMirrors(ctx, orig, results):
		case <-ctx.Done():
			errs <- ctx.Err()
		}
	}()

loop:
	for {
		select {
		case result, ok := <-results:
			if !ok {
				break loop
			}
			fmt.Printf("%s:%s\n", result.Repository, result.Ref)
		case <-ctx.Done():
			return
		}
	}
	fmt.Println(<-errs)

}
Output:

github.com/marstr/mirrorcat:master
github.com/Azure/mirrorcat:dev
<nil>

type MirrorFinder

type MirrorFinder interface {
	FindMirrors(context.Context, RemoteRef, chan<- RemoteRef) error
}

MirrorFinder provides an abstraction for communication which branches on which repositories are mirrors of others.

type PushEvent

type PushEvent struct {
	Ref          string     `json:"ref"`
	Before       string     `json:"before"`
	Size         int        `json:"size"`
	DistinctSize int        `json:"distinct_size"`
	Commits      []Commit   `json:"commits"`
	Head         Commit     `json:"head_commit"`
	Repository   Repository `json:"repository"`
	Pusher       Identity   `json:"pusher"`
}

PushEvent encapsulates all data that will be provided by a GitHub Webhook PushEvent. Read more at: https://developer.github.com/v3/activity/events/types/#pushevent

type RedisFinder

type RedisFinder redis.Client

RedisFinder implementes the MirrorFinder interface against a Redis Cache.

func (RedisFinder) FindMirrors

func (rf RedisFinder) FindMirrors(ctx context.Context, original RemoteRef, results chan<- RemoteRef) error

FindMirrors scrapes a Redis Cache, looking for any mirror entries.

It is expected that the Redis Cache will contain a key which is the result of `mirrorcat.RedisRemoteRef(original).String()`. At that key, MirrorCat expects to find a Set of strings matching the format of the key, but targeting other repositories and refs.

type RedisRemoteRef

type RedisRemoteRef RemoteRef

RedisRemoteRef allows easy conversion to `string` from a `mirrorcat.RemoteRef`.

func ParseRedisRemoteRef

func ParseRedisRemoteRef(input string) (RedisRemoteRef, error)

ParseRedisRemoteRef reads a string formatted as a RedisRemoteRef and reads it into a `mirrorcat.RemoteRef`.

Example
package main

import (
	"fmt"

	"github.com/Azure/mirrorcat"
)

func main() {
	unmarshaled, err := mirrorcat.ParseRedisRemoteRef("master:https://github.com/Azure/mirrorcat")
	if err != nil {
		return
	}

	fmt.Println("Repository:", unmarshaled.Repository)
	fmt.Println("Ref:", unmarshaled.Ref)

}
Output:

Repository: https://github.com/Azure/mirrorcat
Ref: master

func (RedisRemoteRef) String

func (rrr RedisRemoteRef) String() string
Example
package main

import (
	"fmt"

	"github.com/Azure/mirrorcat"
)

func main() {
	subject := mirrorcat.RemoteRef{
		Repository: "https://github.com/Azure/mirrorcat",
		Ref:        "master",
	}

	marshaled := mirrorcat.RedisRemoteRef(subject).String()
	fmt.Println(marshaled)

}
Output:

master:https://github.com/Azure/mirrorcat

type RemoteRef

type RemoteRef struct {
	Repository string `json:"repo"`
	Ref        string `json:"ref"`
}

RemoteRef combines a location with a branch name.

type Repository

type Repository struct {
	ID       int64  `json:"id"`
	Name     string `json:"name"`
	URL      string `json:"url"`
	SSHURL   string `json:"ssh_url"`
	GITURL   string `json:"git_url"`
	CloneURL string `json:"clone_url"`
}

Repository holds metadat about a GitHub URL.

Directories

Path Synopsis
cmd

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL