Skip to content

Commit

Permalink
fork: wait for the actual fork process completion
Browse files Browse the repository at this point in the history
Today, `lab fork` doesn't check if the fork on Gitlab system is indeed
finished, it just assumes so and move on. However, some projects are big
enough to not satisfy it, for instance: the linux kernel. A project
containing the linux kernel source code may take _minutes_ to fork, and the
user will be prompted with an error if the "clone" is not skipped with
--skip-clone.

This patch forces the `lab fork` command to wait the fork completion on
Gitlab system and also adds the "--no-wait" flag if the user really don't
want to wait for anything.

Signed-off-by: Bruno Meneguele <bmeneg@redhat.com>
  • Loading branch information
bmeneg committed Dec 17, 2020
1 parent 1ab3a53 commit 35edd30
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 8 deletions.
28 changes: 22 additions & 6 deletions cmd/fork.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package cmd

import (
"fmt"
"log"
"strings"

Expand All @@ -10,8 +11,11 @@ import (
lab "github.com/zaquestion/lab/internal/gitlab"
)

var skipClone = false
var forkData lab.ForkStruct
var (
skipClone = false
waitFork = true
forkData lab.ForkStruct
)

// forkCmd represents the fork command
var forkCmd = &cobra.Command{
Expand All @@ -22,6 +26,8 @@ var forkCmd = &cobra.Command{
PersistentPreRun: LabPersistentPreRun,
Run: func(cmd *cobra.Command, args []string) {
skipClone, _ = cmd.Flags().GetBool("skip-clone")
noWaitFork, _ := cmd.Flags().GetBool("no-wait")
waitFork = !noWaitFork
forkData.TargetName, _ = cmd.Flags().GetString("name")
forkData.TargetNamespace, _ = cmd.Flags().GetString("namespace")
forkData.TargetPath, _ = cmd.Flags().GetString("path")
Expand Down Expand Up @@ -60,9 +66,13 @@ func forkFromOrigin(cmd *cobra.Command, args []string) {
log.Fatal(err)
}
forkData.SrcProject = project
forkRemoteURL, err := lab.Fork(forkData, useHTTP)
forkRemoteURL, err := lab.Fork(forkData, useHTTP, waitFork)
if err != nil {
log.Fatal(err)
if err.Error() == "not finished" {
fmt.Println("This fork is not ready yet and might take some minutes.")
} else {
log.Fatal(err)
}
}

name := determineForkRemote(project)
Expand All @@ -75,9 +85,14 @@ func forkToUpstream(cmd *cobra.Command, args []string) {
forkData.SrcProject = args[0]
// lab.Fork doesn't have access to the useHTTP var, so we need to pass
// this info to that, so the process works correctly.
_, err := lab.Fork(forkData, useHTTP)
_, err := lab.Fork(forkData, useHTTP, waitFork)
if err != nil {
log.Fatal(err)
if err.Error() == "not finished" && !skipClone {
fmt.Println("This fork is not ready yet and might take some minutes.")
skipClone = true
} else {
log.Fatal(err)
}
}

if !skipClone {
Expand Down Expand Up @@ -112,6 +127,7 @@ func determineForkRemote(project string) string {

func init() {
forkCmd.Flags().BoolP("skip-clone", "s", false, "skip clone after remote fork")
forkCmd.Flags().Bool("no-wait", false, "don't wait for forking operation to finish")
forkCmd.Flags().StringP("name", "n", "", "fork project with a different name")
forkCmd.Flags().StringP("namespace", "m", "", "fork project in a different namespace")
forkCmd.Flags().StringP("path", "p", "", "fork project with a different path")
Expand Down
28 changes: 26 additions & 2 deletions internal/gitlab/gitlab.go
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,7 @@ func (fs ForkStruct) isCustomTargetSet() bool {
}

// Fork creates a user fork of a GitLab project using the specified protocol
func Fork(data ForkStruct, useHTTP bool) (string, error) {
func Fork(data ForkStruct, useHTTP bool, wait bool) (string, error) {
if !strings.Contains(data.SrcProject, "/") {
return "", errors.New("remote must include namespace")
}
Expand All @@ -247,6 +247,10 @@ func Fork(data ForkStruct, useHTTP bool) (string, error) {
return "", err
}

// Now that we have the "wait" opt, don't let the user in the hope that
// something is running.
fmt.Printf("Forking %s project...\n", data.SrcProject)

var forkOpts *gitlab.ForkProjectOptions = nil
if data.isCustomTargetSet() {
forkOpts = &gitlab.ForkProjectOptions{
Expand All @@ -260,11 +264,31 @@ func Fork(data ForkStruct, useHTTP bool) (string, error) {
return "", err
}

// Busy-wait approach for checking the import_status of the fork.
// References:
// https://docs.gitlab.com/ce/api/projects.html#fork-project
// https://docs.gitlab.com/ee/api/project_import_export.html#import-status
status, _, err := lab.ProjectImportExport.ImportStatus(fork.ID, nil)
if wait {
for {
if status.ImportStatus == "finished" {
break
}
status, _, err = lab.ProjectImportExport.ImportStatus(fork.ID, nil)
if err != nil {
log.Fatal(err)
}
time.Sleep(2 * time.Second)
}
} else if status.ImportStatus != "finished" {
err = errors.New("not finished")
}

urlToRepo := fork.SSHURLToRepo
if useHTTP {
urlToRepo = fork.HTTPURLToRepo
}
return urlToRepo, nil
return urlToRepo, err
}

// MRCreate opens a merge request on GitLab
Expand Down

0 comments on commit 35edd30

Please sign in to comment.