Skip to content

Commit

Permalink
capability to manage branches (#20)
Browse files Browse the repository at this point in the history
* feat(repository): introduce repo update functions

This makes it possible for addon writers to interact with the repository
via:

1. creating a branch
2. using the branch
3. adding files to staging
4. commit files
5. push changes to server

Signed-off-by: David Zager <[email protected]>
Signed-off-by: Ankur Mundra <[email protected]>

* feat(repository): add user + email to gitconfig

Signed-off-by: Ankur Mundra <[email protected]>

* repo capabilities for git & svn

Signed-off-by: Ankur Mundra <[email protected]>

* renamed internal function, not exported

Signed-off-by: Ankur Mundra <[email protected]>

Signed-off-by: David Zager <[email protected]>
Signed-off-by: Ankur Mundra <[email protected]>
Co-authored-by: David Zager <[email protected]>
  • Loading branch information
mundra-ankur and djzager authored Nov 10, 2022
1 parent 91dcb11 commit b6cf85c
Show file tree
Hide file tree
Showing 3 changed files with 121 additions and 28 deletions.
6 changes: 2 additions & 4 deletions repository/factory.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ func init() {

type SoftError = hub.SoftError

//
// New SCM repository factory.
func New(destDir string, application *api.Application) (r Repository, err error) {
kind := application.Repository.Kind
Expand All @@ -32,22 +31,21 @@ func New(destDir string, application *api.Application) (r Repository, err error)
return
}

//
// Repository interface.
type Repository interface {
With(path string, application *api.Application)
Fetch() (err error)
Validate() (err error)
Branch(name string) (err error)
Commit(files []string, msg string) (err error)
}

//
// SCM - source code manager.
type SCM struct {
Application *api.Application
Path string
}

//
// With settings.
func (r *SCM) With(path string, application *api.Application) {
r.Application = application
Expand Down
64 changes: 52 additions & 12 deletions repository/git.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,11 @@ import (
"strings"
)

//
// Git repository.
type Git struct {
SCM
}

//
// Validate settings.
func (r *Git) Validate() (err error) {
u := GitURL{}
Expand All @@ -43,7 +41,6 @@ func (r *Git) Validate() (err error) {
return
}

//
// Fetch clones the repository.
func (r *Git) Fetch() (err error) {
url := r.URL()
Expand Down Expand Up @@ -84,15 +81,61 @@ func (r *Git) Fetch() (err error) {
return
}

//
// Branch creates a branch with the given name if not exist and switch to it
func (r *Git) Branch(name string) (err error) {
cmd := command.Command{Path: "/usr/bin/git"}
cmd.Dir = r.Path
cmd.Options.Add("checkout", name)
err = cmd.Run()
if err != nil {
cmd = command.Command{Path: "/usr/bin/git"}
cmd.Dir = r.Path
cmd.Options.Add("checkout", "-b", name)
}
r.Application.Repository.Branch = name
return cmd.Run()
}

// addFiles adds files to staging area
func (r *Git) addFiles(files []string) (err error) {
cmd := command.Command{Path: "/usr/bin/git"}
cmd.Dir = r.Path
cmd.Options.Add("add", files...)
return cmd.Run()
}

// Commit files and push to remote
func (r *Git) Commit(files []string, msg string) (err error) {
err = r.addFiles(files)
if err != nil {
return err
}
cmd := command.Command{Path: "/usr/bin/git"}
cmd.Dir = r.Path
cmd.Options.Add("commit")
cmd.Options.Add("--message", msg)
err = cmd.Run()
if err != nil {
return err
}
return r.push()
}

// push changes to server
func (r *Git) push() (err error) {
cmd := command.Command{Path: "/usr/bin/git"}
cmd.Dir = r.Path
cmd.Options.Add("push", "--set-upstream", "origin", r.Application.Repository.Branch)
return cmd.Run()
}

// URL returns the parsed URL.
func (r *Git) URL() (u GitURL) {
u = GitURL{}
_ = u.With(r.Application.Repository.URL)
return
}

//
// writeConfig writes config file.
func (r *Git) writeConfig() (err error) {
path := pathlib.Join(HomeDir, ".gitconfig")
Expand All @@ -116,7 +159,10 @@ func (r *Git) writeConfig() (err error) {
if err != nil {
return
}
s := "[credential]\n"
s := "[user]\n"
s += "name = Konveyor Dev\n"
s += "email = [email protected]\n"
s += "[credential]\n"
s += "helper = store\n"
s += "[http]\n"
s += fmt.Sprintf("sslVerify = %t\n", !insecure)
Expand All @@ -135,7 +181,6 @@ func (r *Git) writeConfig() (err error) {
return
}

//
// writeCreds writes credentials (store) file.
func (r *Git) writeCreds(id *api.Identity) (err error) {
if id.User == "" || id.Password == "" {
Expand Down Expand Up @@ -184,7 +229,6 @@ func (r *Git) writeCreds(id *api.Identity) (err error) {
return
}

//
// proxy builds the proxy.
func (r *Git) proxy() (proxy string, err error) {
kind := ""
Expand Down Expand Up @@ -236,7 +280,6 @@ func (r *Git) proxy() (proxy string, err error) {
return
}

//
// checkout ref.
func (r *Git) checkout() (err error) {
branch := r.Application.Repository.Branch
Expand All @@ -254,7 +297,6 @@ func (r *Git) checkout() (err error) {
return
}

//
// GitURL git clone URL.
type GitURL struct {
Raw string
Expand All @@ -263,7 +305,6 @@ type GitURL struct {
Path string
}

//
// With populates the URL.
func (r *GitURL) With(u string) (err error) {
r.Raw = u
Expand Down Expand Up @@ -291,7 +332,6 @@ func (r *GitURL) With(u string) (err error) {
return
}

//
// String representation.
func (r *GitURL) String() string {
return r.Raw
Expand Down
79 changes: 67 additions & 12 deletions repository/subversion.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,18 @@ import (
"github.com/konveyor/tackle2-addon/nas"
"github.com/konveyor/tackle2-addon/ssh"
"github.com/konveyor/tackle2-hub/api"
"io/ioutil"
"io"
urllib "net/url"
"os"
pathlib "path"
"strings"
)

//
// Subversion repository.
type Subversion struct {
SCM
}

//
// Validate settings.
func (r *Subversion) Validate() (err error) {
u, err := urllib.Parse(r.Application.Repository.URL)
Expand All @@ -44,11 +42,9 @@ func (r *Subversion) Validate() (err error) {
return
}

//
// Fetch clones the repository.
func (r *Subversion) Fetch() (err error) {
url := r.URL()
_ = nas.RmDir(r.Path)
addon.Activity("[SVN] Cloning: %s", url.String())
id, found, err := addon.Application.FindIdentity(r.Application.ID, "source")
if err != nil {
Expand All @@ -75,6 +71,13 @@ func (r *Subversion) Fetch() (err error) {
if err != nil {
return
}
return r.checkout(r.Application.Repository.Branch)
}

// checkout Checkouts the repository.
func (r *Subversion) checkout(branch string) (err error) {
url := r.URL()
_ = nas.RmDir(r.Path)
insecure, err := addon.Setting.Bool("svn.insecure.enabled")
if err != nil {
return
Expand All @@ -84,25 +87,76 @@ func (r *Subversion) Fetch() (err error) {
if insecure {
cmd.Options.Add("--trust-server-cert")
}

if branch != "" {
url.Path = pathlib.Join(url.RawPath, "branches", branch)
}
cmd.Options.Add("checkout", url.String(), r.Path)
return cmd.Run()
}

func (r *Subversion) Branch(name string) error {
err := r.checkout(name)
if err != nil {
err = r.createBranch(name)
}
return err
}

// createBranch creates a branch with the given name
func (r *Subversion) createBranch(name string) (err error) {
url := *r.URL()
cmd := command.Command{Path: "/usr/bin/svn"}
cmd.Options.Add("--non-interactive")

branchUrl := url
branchUrl.Path = pathlib.Join(branchUrl.RawPath, "branches", name)

cmd.Options.Add("copy", url.String(), branchUrl.String(), "-m", "Creating branch "+name)
err = cmd.Run()
if err != nil {
return err
}
return r.checkout(name)
}

// addFiles adds files to staging area
func (r *Subversion) addFiles(files []string) (err error) {
cmd := command.Command{Path: "/usr/bin/svn"}
cmd.Dir = r.Path
cmd.Options.Add("add")
cmd.Options.Add("--force", files...)
err = cmd.Run()
return
}

// Commit records changes to the repo and push to the server
func (r *Subversion) Commit(files []string, msg string) (err error) {
err = r.addFiles(files)
if err != nil {
return
}
cmd := command.Command{Path: "/usr/bin/svn"}
cmd.Dir = r.Path
cmd.Options.Add("commit", "-m", msg)
err = cmd.Run()
return
}

//
// URL returns the parsed URL.
func (r *Subversion) URL() (u *urllib.URL) {
repository := r.Application.Repository
u, _ = urllib.Parse(repository.URL)
u.RawPath = u.Path
branch := r.Application.Repository.Branch
if branch == "" {
branch = "trunk"
u.Path = pathlib.Join(u.Path, "trunk")
} else {
u.Path = pathlib.Join(u.Path, "branches", branch)
}
u.Path += "/" + branch
return
}

//
// writeConfig writes config file.
func (r *Subversion) writeConfig() (err error) {
path := pathlib.Join(
Expand Down Expand Up @@ -141,12 +195,12 @@ func (r *Subversion) writeConfig() (err error) {
return
}

//
// writePassword injects the password into: auth/svn.simple.
func (r *Subversion) writePassword(id *api.Identity) (err error) {
if id.User == "" || id.Password == "" {
return
}

cmd := command.Command{Path: "/usr/bin/svn"}
cmd.Options.Add("--non-interactive")
cmd.Options.Add("--username")
Expand All @@ -163,6 +217,7 @@ func (r *Subversion) writePassword(id *api.Identity) (err error) {
".subversion",
"auth",
"svn.simple")

files, err := os.ReadDir(dir)
if err != nil {
err = liberr.Wrap(
Expand All @@ -171,6 +226,7 @@ func (r *Subversion) writePassword(id *api.Identity) (err error) {
dir)
return
}

path := pathlib.Join(dir, files[0].Name())
f, err := os.OpenFile(path, os.O_RDWR, 0644)
if err != nil {
Expand All @@ -183,7 +239,7 @@ func (r *Subversion) writePassword(id *api.Identity) (err error) {
defer func() {
_ = f.Close()
}()
content, err := ioutil.ReadAll(f)
content, err := io.ReadAll(f)
if err != nil {
err = liberr.Wrap(
err,
Expand Down Expand Up @@ -224,7 +280,6 @@ func (r *Subversion) writePassword(id *api.Identity) (err error) {
return
}

//
// proxy builds the proxy.
func (r *Subversion) proxy() (proxy string, err error) {
kind := ""
Expand Down

0 comments on commit b6cf85c

Please sign in to comment.