Skip to content
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
9 changes: 9 additions & 0 deletions pkg/git/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
type Client interface {
Checkout(repo Repository, commit string) error
Clone(url, dst string) (*Repository, error)
OpenRepository(path string) (*Repository, error)
}

type ClientImpl struct{}
Expand Down Expand Up @@ -46,3 +47,11 @@ func (c *ClientImpl) Clone(url, dst string) (*Repository, error) {
}
return NewLocalRepository(dst)
}

func (c *ClientImpl) OpenRepository(path string) (*Repository, error) {
_, err := git.PlainOpen(path)
if err != nil {
return nil, fmt.Errorf("failed to open git repository at %s: %w", path, err)
}
return NewLocalRepository(path)
}
6 changes: 6 additions & 0 deletions pkg/git/mocks/mock_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,12 @@ func (m *MockClient) Clone(url, dst string) (*git.Repository, error) {
return args.Get(0).(*git.Repository), args.Error(1)
}

// OpenRepository mocks the OpenRepository method of the Client interface
func (m *MockClient) OpenRepository(path string) (*git.Repository, error) {
args := m.Called(path)
return args.Get(0).(*git.Repository), args.Error(1)
}

// NewMockClient creates and returns a new instance of MockClient
func NewMockClient() *MockClient {
return new(MockClient)
Expand Down
4 changes: 4 additions & 0 deletions pkg/git/repository.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,7 @@ func NewLocalRepository(path string) (*Repository, error) {
}
return &Repository{URL: *u}, nil
}

func (r Repository) IsLocal() bool {
return r.URL.Scheme == "file"
}
29 changes: 29 additions & 0 deletions pkg/lsp/mocks/mock_language_detector.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package mocks

import (
"github.com/hide-org/hide/pkg/model"
"github.com/stretchr/testify/mock"
)

type MockLanguageDetector struct {
mock.Mock
}

func (m *MockLanguageDetector) DetectLanguage(file *model.File) string {
args := m.Called(file)
return args.String(0)
}

func (m *MockLanguageDetector) DetectMainLanguage(files []*model.File) string {
args := m.Called(files)
return args.String(0)
}

func (m *MockLanguageDetector) DetectLanguages(files []*model.File) map[string]int {
args := m.Called(files)
var result map[string]int
if r := args.Get(0); r != nil {
result = r.(map[string]int)
}
return result
}
61 changes: 41 additions & 20 deletions pkg/project/manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"errors"
"fmt"
"io/fs"
"net/url"
"os"
"path"
"sync"
Expand Down Expand Up @@ -102,20 +103,44 @@ func NewProjectManager(
func (pm ManagerImpl) CreateProject(ctx context.Context, request CreateProjectRequest) (*model.Project, error) {
log.Debug().Msgf("Creating project for repo %s", request.Repository.Url)

var (
r *git.Repository
err error
projectPath string
)

// Generate unique project ID
projectId := pm.randomString(10)
projectPath := path.Join(pm.projectsRoot, projectId)

// Clone git repo
if err := pm.createProjectDir(projectPath); err != nil {
log.Error().Err(err).Msg("Failed to create project directory")
return nil, fmt.Errorf("Failed to create project directory: %w", err)
repoUrl, err := url.Parse(request.Repository.Url)
if err != nil {
log.Error().Err(err).Msg("Failed to parse repository URL")
return nil, fmt.Errorf("Failed to parse repository URL: %w", err)
}
repo := git.NewRepository(*repoUrl)

r, err := pm.git.Clone(request.Repository.Url, projectPath)
if err != nil {
log.Error().Err(err).Msg("Failed to clone git repo")
removeProjectDir(projectPath)
return nil, fmt.Errorf("Failed to clone git repo: %w", err)
if repo.IsLocal() {
// For local repositories, use the existing directory
r, err = pm.git.OpenRepository(repo.URL.Path)
if err != nil {
log.Error().Err(err).Msg("Failed to open local git repo")
return nil, fmt.Errorf("Failed to open local git repo: %w", err)
}
projectPath = repo.URL.Path
} else {
// For remote repositories, create directory and clone
projectPath = path.Join(pm.projectsRoot, projectId)

if err := pm.createProjectDir(projectPath); err != nil {
log.Error().Err(err).Msg("Failed to create project directory")
return nil, fmt.Errorf("Failed to create project directory: %w", err)
}
r, err = pm.git.Clone(request.Repository.Url, projectPath)
if err != nil {
log.Error().Err(err).Msg("Failed to clone git repo")
removeProjectDir(projectPath)
return nil, fmt.Errorf("Failed to clone git repo: %w", err)
}
}

if request.Repository.Commit != nil {
Expand All @@ -126,30 +151,26 @@ func (pm ManagerImpl) CreateProject(ctx context.Context, request CreateProjectRe
}
}

// Start devcontainer
var devContainerConfig devcontainer.Config

if request.DevContainer != nil {
devContainerConfig = *request.DevContainer
} else {
// Configure devcontainer
devContainerConfig := request.DevContainer
if devContainerConfig == nil {
config, err := pm.configFromProject(os.DirFS(projectPath))
if err != nil {
log.Error().Err(err).Msgf("Failed to get devcontainer config from repository %s", request.Repository.Url)
removeProjectDir(projectPath)
return nil, fmt.Errorf("Failed to read devcontainer.json: %w", err)
}

devContainerConfig = config
devContainerConfig = &config
}

containerId, err := pm.devContainerRunner.Run(ctx, projectPath, devContainerConfig)
containerId, err := pm.devContainerRunner.Run(ctx, projectPath, *devContainerConfig)
if err != nil {
log.Error().Err(err).Msg("Failed to launch devcontainer")
removeProjectDir(projectPath)
return nil, fmt.Errorf("Failed to launch devcontainer: %w", err)
}

project := model.NewProject(projectId, projectPath, model.Config{DevContainerConfig: devContainerConfig}, containerId, request.Repository)
project := model.NewProject(projectId, projectPath, model.Config{DevContainerConfig: *devContainerConfig}, containerId, request.Repository)

languages := request.Languages
if len(languages) == 0 {
Expand Down