Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add --sync-git-dir flag to odo dev #6910

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -738,7 +738,7 @@ However, this is subject to three things:
- the type of volume created depends on the [configuration of `odo`](../../overview/configure#preference-key-table), and more specifically on the value of the `Ephemeral` setting:
- if `Ephemeral` is `false`, which is the default setting, `odo` creates a [PersistentVolumeClaim](https://kubernetes.io/docs/concepts/storage/persistent-volumes/#persistentvolumeclaims) (PVC) (with the default storage class)
- if `Ephemeral` is `true`, `odo` creates an [`emptyDir`](https://kubernetes.io/docs/concepts/storage/volumes/#emptydir) volume, tied to the lifetime of the Pod.
- the complete content of the current directory and its sub-directories is pushed to the container, except the files listed in the `.odoignore` file, or, if this file is not present, in the `.gitignore` file. `dev.odo.push.path:target` attributes are also considered to push only selected files. See [Pushing Source Files](../../user-guides/advanced/pushing-specific-files) for more details.
- the complete content of the current directory and its sub-directories is pushed to the container, except the files listed in the `.odoignore` file, or, if this file is not present, in the `.gitignore` file. `dev.odo.push.path:target` attributes are also considered to push only selected files. The directory `.git` is not synchronized by default. If you add the `--sync-git-dir` flag to the `odo dev` command, the `.git` repository will be synchronized to the container, regardless of its presence in `.odoignore` or `.gitignore`. See [Pushing Source Files](../../user-guides/advanced/pushing-specific-files) for more details.

| Volume name | Volume Type | Mount Path | Description |
|------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------|-----------------------------------------------|
Expand Down
23 changes: 21 additions & 2 deletions pkg/odo/cli/dev/dev.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,16 @@ import (
"context"
"errors"
"fmt"
apiserver_impl "github.com/redhat-developer/odo/pkg/apiserver-impl"
"github.com/redhat-developer/odo/pkg/odo/cli/feature"
"io"
"path/filepath"
"regexp"
"sort"
"strconv"
"strings"

apiserver_impl "github.com/redhat-developer/odo/pkg/apiserver-impl"
"github.com/redhat-developer/odo/pkg/odo/cli/feature"

"github.com/devfile/api/v2/pkg/apis/workspaces/v1alpha2"
"github.com/spf13/cobra"
"k8s.io/klog/v2"
Expand Down Expand Up @@ -74,6 +75,7 @@ type DevOptions struct {
noCommandsFlag bool
apiServerFlag bool
apiServerPortFlag int
syncGitDirFlag bool
}

var _ genericclioptions.Runnable = (*DevOptions)(nil)
Expand Down Expand Up @@ -239,6 +241,10 @@ func (o *DevOptions) Run(ctx context.Context) (err error) {
// Ignore the devfile, as it will be handled independently
o.ignorePaths = ignores

if o.syncGitDirFlag {
o.ignorePaths = removeGitDir(o.ignorePaths)
}

scontext.SetComponentType(ctx, component.GetComponentTypeFromDevfileMetadata(devFileObj.Data.GetMetadata()))
scontext.SetLanguage(ctx, devFileObj.Data.GetMetadata().Language)
scontext.SetProjectType(ctx, devFileObj.Data.GetMetadata().ProjectType)
Expand Down Expand Up @@ -278,6 +284,18 @@ func (o *DevOptions) Run(ctx context.Context) (err error) {
)
}

// removeGitDir removes the `.git` entry from the list of paths to ignore
// and adds `!.git`, to force the sync of all files into the .git directory
func removeGitDir(ignores []string) []string {
ignores = append(ignores, "!.git")
for i, entry := range ignores {
if entry == ".git" {
return append(ignores[0:i], ignores[i+1:]...)
}
}
return ignores
}

func (o *DevOptions) HandleSignal(ctx context.Context, cancelFunc context.CancelFunc) error {
cancelFunc()
// At this point, `ctx.Done()` will be raised, and the cleanup will be done
Expand Down Expand Up @@ -325,6 +343,7 @@ It forwards endpoints with any exposure values ('public', 'internal' or 'none')
"Define custom port mapping for port forwarding. Acceptable formats: LOCAL_PORT:REMOTE_PORT, LOCAL_PORT:CONTAINER_NAME:REMOTE_PORT.")
devCmd.Flags().StringVar(&o.addressFlag, "address", "127.0.0.1", "Define custom address for port forwarding.")
devCmd.Flags().BoolVar(&o.noCommandsFlag, "no-commands", false, "Do not run any commands; just start the development environment.")
devCmd.Flags().BoolVar(&o.syncGitDirFlag, "sync-git-dir", false, "Synchronize the .git directory to the container. By default, this directory is not synchronized.")

if feature.IsExperimentalModeEnabled(ctx) {
devCmd.Flags().BoolVar(&o.apiServerFlag, "api-server", false, "Start the API Server; this is an experimental feature")
Expand Down
2 changes: 1 addition & 1 deletion pkg/util/file_indexer.go
Original file line number Diff line number Diff line change
Expand Up @@ -462,7 +462,7 @@ func recursiveChecker(pathOptions recursiveCheckerPathOptions, ignoreRules []str

if stat.IsDir() {

if stat.Name() == DotOdoDirectory || stat.Name() == ".git" {
if stat.Name() == DotOdoDirectory {
return IndexerRet{}, nil
}

Expand Down
28 changes: 0 additions & 28 deletions pkg/util/file_indexer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -256,24 +256,6 @@ func createAndStat(fileName, tempDirectoryName string, fs filesystem.Filesystem)
return file, stat, nil
}

func createGitFolderAndFiles(tempDirectoryName string, fs filesystem.Filesystem) error {
err := fs.MkdirAll(filepath.Join(tempDirectoryName, ".git"), 0755)
if err != nil {
return err
}

err = fs.MkdirAll(filepath.Join(tempDirectoryName, DotOdoDirectory), 0755)
if err != nil {
return err
}

_, err = fs.Create(filepath.Join(tempDirectoryName, ".git", "someFile.txt"))
if err != nil {
return err
}
return nil
}

func Test_recursiveChecker(t *testing.T) {
fs := filesystem.DefaultFs{}

Expand All @@ -282,11 +264,6 @@ func Test_recursiveChecker(t *testing.T) {
t.Errorf("unexpected error: %v", err)
}

err = createGitFolderAndFiles(tempDirectoryName, fs)
if err != nil {
t.Errorf("unexpected error: %v", err)
}

jsFileName := "red.js"
jsFile, jsFileStat, err := createAndStat(jsFileName, tempDirectoryName, fs)
if err != nil {
Expand Down Expand Up @@ -1179,11 +1156,6 @@ func Test_runIndexerWithExistingFileIndex(t *testing.T) {
t.Errorf("unexpected error: %v", err)
}

err = createGitFolderAndFiles(tempDirectoryName, fs)
if err != nil {
t.Errorf("unexpected error: %v", err)
}

jsFileName := "red.js"
jsFile, jsFileStat, err := createAndStat(jsFileName, tempDirectoryName, fs)
if err != nil {
Expand Down
4 changes: 4 additions & 0 deletions tests/helper/helper_dev.go
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ type DevSessionOpts struct {
CustomAddress string
StartAPIServer bool
APIServerPort int
SyncGitDir bool
}

// StartDevMode starts a dev session with `odo dev`
Expand Down Expand Up @@ -166,6 +167,9 @@ func StartDevMode(options DevSessionOpts) (devSession DevSession, err error) {
args = append(args, "--api-server-port", fmt.Sprintf("%d", options.APIServerPort))
}
}
if options.SyncGitDir {
args = append(args, "--sync-git-dir")
}
args = append(args, options.CmdlineArgs...)
cmd := Cmd("odo", args...)
cmd.Cmd.Stdin = c.Tty()
Expand Down
34 changes: 34 additions & 0 deletions tests/integration/cmd_dev_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,40 @@ echo "$@"

for _, podman := range []bool{true, false} {
podman := podman
It("should not sync .git directory", helper.LabelPodmanIf(podman, func() {
helper.MakeDir(".git")
err := helper.CreateFileWithContent(filepath.Join(commonVar.Context, ".git", "file.txt"), "aze")
Expect(err).ToNot(HaveOccurred())
helper.MakeDir("notgit")
err = helper.CreateFileWithContent(filepath.Join(commonVar.Context, "notgit", "otherfile.txt"), "aze")
Expect(err).ToNot(HaveOccurred())
err = helper.RunDevMode(helper.DevSessionOpts{
RunOnPodman: podman,
}, func(session *gexec.Session, outContents, errContents string, ports map[string]string) {
component := helper.NewComponent(cmpName, "app", labels.ComponentDevMode, commonVar.Project, commonVar.CliRunner)
component.Exec("runtime", []string{"ls", "/projects/.git/file.txt"}, pointer.Bool(false))
component.Exec("runtime", []string{"ls", "/projects/notgit/otherfile.txt"}, pointer.Bool(true))
})
Expect(err).ToNot(HaveOccurred())
}))
It("should sync .git directory and subfiles with --sync-git-dir", helper.LabelPodmanIf(podman, func() {
gitignorePath := filepath.Join(commonVar.Context, ".gitignore")
if err := helper.CreateFileWithContent(gitignorePath, `file.txt`); err != nil {
fmt.Printf("the .gitignore file was not created, reason %v", err.Error())
}
helper.MakeDir(".git")
err := helper.CreateFileWithContent(filepath.Join(commonVar.Context, ".git", "file.txt"), "aze")
Expect(err).ToNot(HaveOccurred())
err = helper.RunDevMode(helper.DevSessionOpts{
RunOnPodman: podman,
SyncGitDir: true,
}, func(session *gexec.Session, outContents, errContents string, ports map[string]string) {
component := helper.NewComponent(cmpName, "app", labels.ComponentDevMode, commonVar.Project, commonVar.CliRunner)
component.Exec("runtime", []string{"ls", "/projects/.git/file.txt"}, pointer.Bool(true))
})
Expect(err).ToNot(HaveOccurred())
}))

It("should use the index information from previous push operation", helper.LabelPodmanIf(podman, func() {
// Create a new file A
fileAPath, fileAText := helper.CreateSimpleFile(commonVar.Context, "my-file-", ".txt")
Expand Down