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
23 changes: 13 additions & 10 deletions internal/adapters/primary/cli/new.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ const (
)

var (
projectType string
quietNew bool
projectType string //nolint:gochecknoglobals // cobra flag variable
quietNew bool //nolint:gochecknoglobals // cobra flag variable
)

const dprTemplate = `program %s;
Expand Down Expand Up @@ -120,7 +120,8 @@ const dprojTemplate = `<Project xmlns="http://schemas.microsoft.com/developer/ms
<ProjectFileVersion>12</ProjectFileVersion>
</ProjectExtensions>
<Import Project="$(BDS)\Bin\CodeGear.Delphi.Targets" Condition="Exists('$(BDS)\Bin\CodeGear.Delphi.Targets')"/>
<Import Project="$(APPDATA)\Embarcadero\$(BDSAPPDATABASEDIR)\$(PRODUCTVERSION)\UserTools.proj" Condition="Exists('$(APPDATA)\Embarcadero\$(BDSAPPDATABASEDIR)\$(PRODUCTVERSION)\UserTools.proj')"/>
<Import Project="$(APPDATA)\Embarcadero\$(BDSAPPDATABASEDIR)\$(PRODUCTVERSION)\UserTools.proj"
Condition="Exists('$(APPDATA)\Embarcadero\$(BDSAPPDATABASEDIR)\$(PRODUCTVERSION)\UserTools.proj')"/>
</Project>
`

Expand All @@ -138,16 +139,16 @@ func generateGUID() string {
// newCmdRegister registers the new command.
func newCmdRegister(root *cobra.Command) {
var newCmd = &cobra.Command{
Use: "new [project_name]",
Short: "Create a new Delphi project skeleton",
Long: "Create a new Delphi project skeleton with source directories, templates, and boss.json",
Args: cobra.MaximumNArgs(1),
Use: "new [project_name]",
Short: "Create a new Delphi project skeleton",
Long: "Create a new Delphi project skeleton with source directories, templates, and boss.json",
Args: cobra.MaximumNArgs(1),
Example: ` Create a new console application:
boss new my_project

Create a new package/library:
boss new my_package --type pkg`,
Run: func(cmd *cobra.Command, args []string) {
Run: func(_ *cobra.Command, args []string) {
var name string
if len(args) > 0 {
name = args[0]
Expand Down Expand Up @@ -194,9 +195,11 @@ func doCreateProject(name string, pType string, quiet bool) {
// Create directories
srcDir := filepath.Join(projectDir, "src")
testsDir := filepath.Join(projectDir, "tests")
//nolint:gosec // Standard directory permissions
if err := os.MkdirAll(srcDir, 0755); err != nil {
msg.Die("❌ Failed to create src directory: %v", err)
}
//nolint:gosec // Standard directory permissions
if err := os.MkdirAll(testsDir, 0755); err != nil {
msg.Die("❌ Failed to create tests directory: %v", err)
}
Expand All @@ -207,8 +210,8 @@ func doCreateProject(name string, pType string, quiet bool) {
packageData.Version = defaultPackageVersion
packageData.MainSrc = "src"

packageJsonPath := filepath.Join(projectDir, consts.FilePackage)
if err := pkgmanager.SavePackage(packageData, packageJsonPath); err != nil {
packageJSONPath := filepath.Join(projectDir, consts.FilePackage)
if err := pkgmanager.SavePackage(packageData, packageJSONPath); err != nil {
msg.Die("❌ Failed to save boss.json: %v", err)
}

Expand Down
46 changes: 18 additions & 28 deletions internal/adapters/primary/cli/new_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,11 @@ func TestNewCommandRegistration(t *testing.T) {
}

typeFlag := newCmd.Flags().Lookup("type")
//nolint:staticcheck // Test intentionally keeps non-fatal assertion before the follow-up check
if typeFlag == nil {
t.Error("New command should have --type flag")
}
//nolint:staticcheck // Test handles nil case with t.Error
if typeFlag.DefValue != "app" {
t.Errorf("New command --type flag default value should be 'app', got %s", typeFlag.DefValue)
}
Expand All @@ -55,15 +57,9 @@ func TestNewCommandRegistration(t *testing.T) {
// TestDoCreateProject_App tests bootstrapping an application project.
func TestDoCreateProject_App(t *testing.T) {
tempDir := t.TempDir()
t.Chdir(tempDir)

// Redirect working directory
oldWd, err := os.Getwd()
if err == nil {
defer func() { _ = os.Chdir(oldWd) }()
}
if err := os.Chdir(tempDir); err != nil {
t.Fatalf("Failed to change directory: %v", err)
}
var err error

// Initialize package manager
fs := filesystem.NewOSFileSystem()
Expand All @@ -76,31 +72,31 @@ func TestDoCreateProject_App(t *testing.T) {
doCreateProject(projectName, "app", true)

projectPath := filepath.Join(tempDir, projectName)
if _, err := os.Stat(projectPath); os.IsNotExist(err) {
if _, statErr := os.Stat(projectPath); os.IsNotExist(statErr) {
t.Fatalf("Project directory was not created")
}

// Check folders
if _, err := os.Stat(filepath.Join(projectPath, "src")); os.IsNotExist(err) {
if _, statErr := os.Stat(filepath.Join(projectPath, "src")); os.IsNotExist(statErr) {
t.Error("src directory was not created")
}
if _, err := os.Stat(filepath.Join(projectPath, "tests")); os.IsNotExist(err) {
if _, statErr := os.Stat(filepath.Join(projectPath, "tests")); os.IsNotExist(statErr) {
t.Error("tests directory was not created")
}

// Check boss.json
bossJsonPath := filepath.Join(projectPath, consts.FilePackage)
if _, err := os.Stat(bossJsonPath); os.IsNotExist(err) {
bossJSONPath := filepath.Join(projectPath, consts.FilePackage)
if _, statErr := os.Stat(bossJSONPath); os.IsNotExist(statErr) {
t.Fatal("boss.json was not created")
}

bossBytes, err := os.ReadFile(bossJsonPath)
bossBytes, err := os.ReadFile(bossJSONPath)
if err != nil {
t.Fatalf("Failed to read boss.json: %v", err)
}

var pkg domain.Package
if err := json.Unmarshal(bossBytes, &pkg); err != nil {
if err = json.Unmarshal(bossBytes, &pkg); err != nil {
t.Fatalf("Failed to parse boss.json: %v", err)
}

Expand All @@ -116,7 +112,7 @@ func TestDoCreateProject_App(t *testing.T) {

// Check .dpr file
dprPath := filepath.Join(projectPath, projectName+".dpr")
if _, err := os.Stat(dprPath); os.IsNotExist(err) {
if _, statErr := os.Stat(dprPath); os.IsNotExist(statErr) {
t.Fatal(".dpr file was not created")
}

Expand All @@ -131,7 +127,7 @@ func TestDoCreateProject_App(t *testing.T) {

// Check .dproj file
dprojPath := filepath.Join(projectPath, projectName+".dproj")
if _, err := os.Stat(dprojPath); os.IsNotExist(err) {
if _, statErr := os.Stat(dprojPath); os.IsNotExist(statErr) {
t.Fatal(".dproj file was not created")
}

Expand All @@ -151,15 +147,9 @@ func TestDoCreateProject_App(t *testing.T) {
// TestDoCreateProject_Pkg tests bootstrapping a package project.
func TestDoCreateProject_Pkg(t *testing.T) {
tempDir := t.TempDir()
t.Chdir(tempDir)

// Redirect working directory
oldWd, err := os.Getwd()
if err == nil {
defer func() { _ = os.Chdir(oldWd) }()
}
if err := os.Chdir(tempDir); err != nil {
t.Fatalf("Failed to change directory: %v", err)
}
var err error

// Initialize package manager
fs := filesystem.NewOSFileSystem()
Expand All @@ -172,13 +162,13 @@ func TestDoCreateProject_Pkg(t *testing.T) {
doCreateProject(projectName, "pkg", true)

projectPath := filepath.Join(tempDir, projectName)
if _, err := os.Stat(projectPath); os.IsNotExist(err) {
if _, statErr := os.Stat(projectPath); os.IsNotExist(statErr) {
t.Fatalf("Project directory was not created")
}

// Check .dpk file
dpkPath := filepath.Join(projectPath, projectName+".dpk")
if _, err := os.Stat(dpkPath); os.IsNotExist(err) {
if _, statErr := os.Stat(dpkPath); os.IsNotExist(statErr) {
t.Fatal(".dpk file was not created")
}

Expand All @@ -193,7 +183,7 @@ func TestDoCreateProject_Pkg(t *testing.T) {

// Check .dproj file
dprojPath := filepath.Join(projectPath, projectName+".dproj")
if _, err := os.Stat(dprojPath); os.IsNotExist(err) {
if _, statErr := os.Stat(dprojPath); os.IsNotExist(statErr) {
t.Fatal(".dproj file was not created")
}

Expand Down
10 changes: 6 additions & 4 deletions internal/core/services/compiler/executor.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,26 +75,28 @@ func compileLazarus(lazarusPath string, tracker *BuildTracker) bool {
absPath, _ := filepath.Abs(lazarusPath)
absDir := filepath.Dir(absPath)

cmd := exec.Command("lazbuild", "--build-mode=Debug", absPath)
// #nosec G204 -- Controlled lazbuild command
cmd := exec.CommandContext(context.Background(), "lazbuild", "--build-mode=Debug", absPath)
cmd.Dir = absDir

baseName := strings.TrimSuffix(filepath.Base(lazarusPath), filepath.Ext(lazarusPath))
buildLog := filepath.Join(absDir, "build_boss_"+baseName+".log")
// #nosec G304 -- Controlled build log path
logFile, err := os.OpenFile(buildLog, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0600)
if err != nil {
if tracker == nil || !tracker.IsEnabled() {
msg.Warn(" ⚠️ Error creating build log file: %v", err)
}
return false
}
defer logFile.Close()
defer func() { _ = logFile.Close() }()

cmd.Stdout = logFile
cmd.Stderr = logFile

if err := cmd.Run(); err != nil {
if tracker == nil || !tracker.IsEnabled() {
msg.Err(" ❌ Failed to compile, see " + buildLog + " for more information: %v", err)
msg.Err(" ❌ Failed to compile, see "+buildLog+" for more information: %v", err)
}
return false
}
Expand All @@ -107,7 +109,7 @@ func compileLazarus(lazarusPath string, tracker *BuildTracker) bool {
return true
}

//nolint:funlen,gocognit,lll // Complex compilation orchestration with long function signature
//nolint:funlen,gocognit,gocyclo,cyclop,lll // Complex compilation orchestration
func compile(dprojPath string, dep *domain.Dependency, rootLock domain.PackageLock, tracker *BuildTracker, selectedCompiler *compilerselector.SelectedCompiler) bool {
ext := strings.ToLower(filepath.Ext(dprojPath))
if ext == ".lpi" || ext == ".lpk" {
Expand Down
10 changes: 8 additions & 2 deletions internal/core/services/compilerselector/selector.go
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,10 @@ func resolveTargetPlatform(ctx SelectionContext) string {
}
}

func findGlobalPathCompiler(installations []registryadapter.DelphiInstallation, globalPath, targetPlatform string) (*SelectedCompiler, error) {
func findGlobalPathCompiler(
installations []registryadapter.DelphiInstallation,
globalPath, targetPlatform string,
) (*SelectedCompiler, error) {
for _, inst := range installations {
instDir := filepath.Dir(inst.Path)
if strings.EqualFold(instDir, globalPath) && strings.EqualFold(inst.Arch, targetPlatform) {
Expand All @@ -118,7 +121,10 @@ func findGlobalPathCompiler(installations []registryadapter.DelphiInstallation,
}, nil
}

func findLatestCompiler(installations []registryadapter.DelphiInstallation, targetPlatform string) (*SelectedCompiler, error) {
func findLatestCompiler(
installations []registryadapter.DelphiInstallation,
targetPlatform string,
) (*SelectedCompiler, error) {
var bestMatch *registryadapter.DelphiInstallation
for _, inst := range installations {
if strings.EqualFold(inst.Arch, targetPlatform) {
Expand Down
4 changes: 2 additions & 2 deletions internal/core/services/compilerselector/selector_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import (
"github.com/hashload/boss/pkg/env"
)

// mockRegistryAdapter is a mock for compilerselector.RegistryAdapter
// mockRegistryAdapter is a mock for compilerselector.RegistryAdapter.
type mockRegistryAdapter struct {
installations []registryadapter.DelphiInstallation
}
Expand All @@ -19,7 +19,7 @@ func (m *mockRegistryAdapter) GetDetectedDelphis() []registryadapter.DelphiInsta
return m.installations
}

// mockConfigProvider embeds env.ConfigProvider to mock only GetDelphiPath
// mockConfigProvider embeds env.ConfigProvider to mock only GetDelphiPath.
type mockConfigProvider struct {
env.ConfigProvider
delphiPath string
Expand Down
10 changes: 5 additions & 5 deletions internal/core/services/installer/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ var (
)

// parseURLAndVersion parses the dependency URL and version, handling SSH git@ URLs safely.
func parseURLAndVersion(input string) (url string, version string) {
func parseURLAndVersion(input string) (string, string) {
if strings.HasPrefix(input, "git@") {
// SSH URL format: git@host:owner/repo[.git][:version] or git@host:owner/repo[.git]@version
firstColon := strings.Index(input, ":")
Expand All @@ -35,8 +35,8 @@ func parseURLAndVersion(input string) (url string, version string) {
possibleVersion := remainder[lastSep+1:]
// Version shouldn't contain slashes (which paths do) and shouldn't be empty
if !strings.Contains(possibleVersion, "/") && possibleVersion != "" {
url = input[:firstColon+1+lastSep]
version = possibleVersion
url := input[:firstColon+1+lastSep]
version := possibleVersion
return url, version
}
}
Expand All @@ -54,8 +54,8 @@ func parseURLAndVersion(input string) (url string, version string) {
}
}

url = match["url"]
version = match["version"]
url := match["url"]
version := match["version"]
return url, version
}

Expand Down
9 changes: 4 additions & 5 deletions internal/core/services/installer/utils_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -160,10 +160,10 @@ func TestEnsureDependency_HTTPSUrl(t *testing.T) {

func TestEnsureDependency_SSHUrl(t *testing.T) {
tests := []struct {
name string
input string
expectedDep string
expectedVer string
name string
input string
expectedDep string
expectedVer string
}{
{
name: "SSH URL with version tag",
Expand Down Expand Up @@ -225,4 +225,3 @@ func TestEnsureDependency_SSHUrl(t *testing.T) {
})
}
}

1 change: 0 additions & 1 deletion utils/dcp/dcp_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -227,4 +227,3 @@ end.`
t.Error("injectDcps() should preserve AnotherPkg dependency")
}
}

12 changes: 3 additions & 9 deletions utils/librarypath/lazarus_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,15 +55,9 @@ const mockLpkContent = `<?xml version="1.0" encoding="UTF-8"?>
// TestLazarusPathInjection verifies that other unit search paths are correctly injected in both .lpi and .lpk files.
func TestLazarusPathInjection(t *testing.T) {
tempDir := t.TempDir()
t.Chdir(tempDir)

// Redirect working directory
oldWd, err := os.Getwd()
if err == nil {
defer func() { _ = os.Chdir(oldWd) }()
}
if err = os.Chdir(tempDir); err != nil {
t.Fatalf("Failed to change directory: %v", err)
}
var err error

// Initialize package manager
fs := filesystem.NewOSFileSystem()
Expand Down Expand Up @@ -141,7 +135,7 @@ func TestLazarusPathInjection(t *testing.T) {

// Verify LPK XML contents
docLpk := etree.NewDocument()
if err := docLpk.ReadFromFile(lpkPath); err != nil {
if err = docLpk.ReadFromFile(lpkPath); err != nil {
t.Fatalf("Failed to read updated LPK: %v", err)
}

Expand Down
Loading
Loading