Skip to content

Commit

Permalink
Merge pull request #3 from uddugteam/forking
Browse files Browse the repository at this point in the history
Forking
  • Loading branch information
andskur authored Feb 20, 2023
2 parents afd7e05 + 29f440b commit 1a87abe
Show file tree
Hide file tree
Showing 3 changed files with 127 additions and 34 deletions.
13 changes: 12 additions & 1 deletion .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -63,4 +63,15 @@ jobs:
tag: ${{ steps.tag_version.outputs.new_tag }}
name: ${{ steps.tag_version.outputs.new_tag }}
body: ${{ steps.tag_version.outputs.changelog }}
token: ${{ secrets.RELEASES_ACTION_GITHUB_TOKEN }}
token: ${{ secrets.RELEASES_ACTION_GITHUB_TOKEN }}

deploy:
needs: build
name: Deploy App on digital ocean
runs-on: ubuntu-latest
steps:
- name: DigitalOcean App Platform deployment
uses: digitalocean/app_action@main
with:
app_name: andskur-gitsec-backend
token: ${{ secrets.DIGITALOCEAN_ACCESS_TOKEN }}
25 changes: 19 additions & 6 deletions internal/models/repo.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ type Repo struct {

Metadata string

ForkFrom string

// fileSystem is the filesystem where the repository is stored.
fileSystem billy.Filesystem
// server is the transport server used to handle git sessions.
Expand All @@ -46,13 +48,14 @@ type Repo struct {
}

// NewRepo creates a new Repo instance.
func NewRepo(name, description, basePath string, id int, owner common.Address, fs billy.Filesystem) (*Repo, error) {
func NewRepo(name, description, basePath, forkFrom string, id int, owner common.Address, fs billy.Filesystem) (*Repo, error) {
repo := &Repo{
Name: name,
Description: description,
BasePath: basePath,
ID: id,
Owner: owner,
ForkFrom: forkFrom,
}

if err := repo.InitRepo(fs); err != nil {
Expand Down Expand Up @@ -92,12 +95,22 @@ func (r *Repo) InitRepo(fs billy.Filesystem) (err error) {
// If the file system does not already exist, a new repository is created.
func (r *Repo) initFileSystem() (err error) {
if !r.isRepoFSExists() {
r.Repocore, err = git.Init(filesystem.NewStorage(r.fileSystem, cache.NewObjectLRU(500)), nil)
if err != nil {
if errors.Is(err, git.ErrRepositoryAlreadyExists) {
return nil
if r.ForkFrom != "" {
r.Repocore, err = git.Clone(filesystem.NewStorage(r.fileSystem, cache.NewObjectLRU(500)), nil, &git.CloneOptions{
URL: r.ForkFrom,
RecurseSubmodules: git.DefaultSubmoduleRecursionDepth,
})
if err != nil {
return fmt.Errorf("failed to clone Repocore on fs: %w", err)
}
} else {
r.Repocore, err = git.Init(filesystem.NewStorage(r.fileSystem, cache.NewObjectLRU(500)), nil)
if err != nil {
if errors.Is(err, git.ErrRepositoryAlreadyExists) {
return nil
}
return fmt.Errorf("failed to create new Repocore on fs: %w", err)
}
return fmt.Errorf("failed to create new Repocore on fs: %w", err)
}
} else {
r.Repocore, err = git.Open(filesystem.NewStorage(r.fileSystem, cache.NewObjectLRU(500)), nil)
Expand Down
123 changes: 96 additions & 27 deletions internal/service/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -125,9 +125,51 @@ func NewGitService(cfg *config.Scheme, blockchain *ethclient.Client) (*GitServic
}, nil
}

// TODO move events listeners to separate package

func (g *GitService) StartListener() {
if err := g.ListenRepositoryCreation(); err != nil {
logger.Log().Error(err)
go func() {
if err := g.ListenRepositoryCreation(); err != nil {
logger.Log().Error(err)
}
}()

go func() {
if err := g.ListenRepositoryForks(); err != nil {
logger.Log().Error(err)
}
}()
}

func (g *GitService) ListenRepositoryForks() error {
repos := make(chan *contract.ContractRepositoryForked)
opts := &bind.WatchOpts{Context: context.Background()}

Subscribe:
repositoryForksSubscriptions, err := g.contract.WatchRepositoryForked(opts, repos)
if err != nil {
return fmt.Errorf("failed subscribe to watch transfers event: %w", err)
}
defer repositoryForksSubscriptions.Unsubscribe()

logger.Log().Infof("listen contract repository fork events on %s", g.contractAddress.Hex())

for {
select {
case <-g.stop:
logger.Log().Warning("stop listen contract repository forks events")
close(repos)
return nil
case err := <-repositoryForksSubscriptions.Err():
logger.Log().Error(fmt.Errorf("repository forks subscription error: %w", err))
goto Subscribe
case r := <-repos:
logger.Log().Infof("catch repository forks event: repository %s with ID %d forked from %s created with owner %s", r.RepName, r.RepId, r.Url, r.Owner.Hex())

if err := g.CloneRepo(r.RepName, r.Description, r.Url, int(r.RepId.Int64()), r.Owner); err != nil {
logger.Log().Error(fmt.Errorf("error to fork repository: %w", err))
}
}
}
}

Expand All @@ -147,7 +189,7 @@ Subscribe:
for {
select {
case <-g.stop:
logger.Log().Warning("stop listen contract transfers events")
logger.Log().Warning("stop listen contract repository creation events")
close(repos)
return nil
case err := <-repositoryCreationSubscriptions.Err():
Expand All @@ -163,12 +205,37 @@ Subscribe:
}
}

func (g *GitService) CloneRepo(name, description, forkFrom string, id int, owner common.Address) error {
repo, err := models.NewRepo(name, description, g.baseGitPath, forkFrom, id, owner, g.fs)
if err != nil {
return fmt.Errorf("failed to create new repo: %w", err)
}

if err := g.processNewRepo(repo); err != nil {
return fmt.Errorf("process new repo: %w", err)
}

if err := g.updateRepositoryMeta(repo); err != nil {
return fmt.Errorf("failed to update repository meta: %w", err)
}

return nil
}

func (g *GitService) CreateRepo(name, description string, id int, owner common.Address) error {
repo, err := models.NewRepo(name, description, g.baseGitPath, id, owner, g.fs)
repo, err := models.NewRepo(name, description, g.baseGitPath, "", id, owner, g.fs)
if err != nil {
return fmt.Errorf("failed to create new repo: %w", err)
}

if err := g.processNewRepo(repo); err != nil {
return fmt.Errorf("process new repo: %w", err)
}

return nil
}

func (g *GitService) processNewRepo(repo *models.Repo) error {
meta, err := repo.GenMeta()
if err != nil {
return fmt.Errorf("failed to generate repository meta: %w", err)
Expand All @@ -179,12 +246,12 @@ func (g *GitService) CreateRepo(name, description string, id int, owner common.A
return fmt.Errorf("marshal repository metadata: %w", err)
}

hash, err := g.pinner.Pin(name+"-meta.json", bytes.NewReader(metaJson))
hash, err := g.pinner.Pin(repo.Name+"-meta.json", bytes.NewReader(metaJson))
if err != nil {
return fmt.Errorf("pin repository metadata to ipfs: %w", err)
}

logger.Log().Infof("repository %s metadata %s pinned to IPFS", name, hash)
logger.Log().Infof("repository %s metadata %s pinned to IPFS", repo.Name, hash)

repo.Metadata = hash

Expand All @@ -204,13 +271,7 @@ func (g *GitService) CreateRepo(name, description string, id int, owner common.A
return fmt.Errorf("failed to send transaction: %w", err)
}

logger.Log().Infof("transaction %s to update repository %s ID %d metadata %s send to blockchan", tx.Hash().Hex(), name, repo.ID, hash)

rewrewr := &models.Repo{Name: name}

if err := g.repository.GetRepo(rewrewr); err != nil {
return err
}
logger.Log().Infof("transaction %s to update repository %s ID %d metadata %s send to blockchan", tx.Hash().Hex(), repo.Name, repo.ID, hash)

return nil
}
Expand Down Expand Up @@ -291,60 +352,68 @@ func (g *GitService) ReceivePack(ctx context.Context, req io.Reader, repositoryN

logger.Log().Infof("recieve pack handled in %s", time.Since(start))

if err := g.updateRepositoryMeta(repo); err != nil {
return nil, fmt.Errorf("failed to update repository meta: %w", err)
}

return res, nil
}

func (g *GitService) updateRepositoryMeta(repo *models.Repo) error {
head, err := repo.Head()
if err != nil {
return nil, fmt.Errorf("failed to get repo head: %w", err)
return fmt.Errorf("failed to get repo head: %w", err)
}

tree, err := repo.Tree(head.Hash())
if err != nil {
return nil, fmt.Errorf("failed to get repo tree: %w", err)
return fmt.Errorf("failed to get repo tree: %w", err)
}

meta, err := repo.GenMeta()
if err != nil {
return nil, fmt.Errorf("failed to generate repository meta: %w", err)
return fmt.Errorf("failed to generate repository meta: %w", err)
}

if err := meta.FillContent(tree); err != nil {
return nil, fmt.Errorf("failed to fill metadata content: %w", err)
return fmt.Errorf("failed to fill metadata content: %w", err)
}

if err := meta.FillCommit(repo); err != nil {
return nil, fmt.Errorf("failed to fill metadata tree commits: %w", err)
return fmt.Errorf("failed to fill metadata tree commits: %w", err)
}

if err := g.StoreMetaTree(meta, repo); err != nil {
return nil, fmt.Errorf("failed to store metadata content: %w", err)
return fmt.Errorf("failed to store metadata content: %w", err)
}

metaBytes, err := json.Marshal(meta)
if err != nil {
return nil, fmt.Errorf("marshal repository metadata: %w", err)
return fmt.Errorf("marshal repository metadata: %w", err)
}

hash, err := g.pinner.Pin(fmt.Sprintf("%s-%d-meta.json", repositoryName, time.Now().Unix()), bytes.NewReader(metaBytes))
hash, err := g.pinner.Pin(fmt.Sprintf("%s-%d-meta.json", repo.Name, time.Now().Unix()), bytes.NewReader(metaBytes))
if err != nil {
return nil, fmt.Errorf("pin repository metadata to ipfs: %w", err)
return fmt.Errorf("pin repository metadata to ipfs: %w", err)
}

logger.Log().Infof("repository %s metadata %s pinned to IPFS", repositoryName, hash)
logger.Log().Infof("repository %s metadata %s pinned to IPFS", repo.Name, hash)

repo.Metadata = hash

sign, err := g.signer.Sign(g.chainId)
if err != nil {
return nil, fmt.Errorf("prepare tx signing: %w", err)
return fmt.Errorf("prepare tx signing: %w", err)
}

tx, err := g.contract.UpdateIPFS(sign, big.NewInt(int64(repo.ID)), hash)
if err != nil {
return nil, fmt.Errorf("failed to send transaction: %w", err)
return fmt.Errorf("failed to send transaction: %w", err)
}

logger.Log().Infof("transaction %s to update repository %s ID %d metadata %s send to blockchan", tx.Hash().Hex(), repositoryName, repo.ID, hash)
logger.Log().Infof("transaction %s to update repository %s ID %d metadata %s send to blockchan", tx.Hash().Hex(), repo.Name, repo.ID, hash)

return res, nil
return nil
}

func (g *GitService) StoreMetaTree(meta *models.RepoMetadata, repo *models.Repo) error {
Expand Down

0 comments on commit 1a87abe

Please sign in to comment.