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

no such file or directory errors fix #58

Merged
merged 11 commits into from
Jul 13, 2024
Merged
Show file tree
Hide file tree
Changes from 4 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
4 changes: 3 additions & 1 deletion CONTRIBUTORS.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,6 @@ We contributors to BuildSafe:
* Praful(@Horiodino)
* Sanyam(@sanyamjain04)
* Hanshal(@hanshal101)
* Balaaditya(@BalaadityaPatanjali)
* Manik(@manik2708)
* Balaaditya(@BalaadityaPatanjali)

5 changes: 5 additions & 0 deletions cmd/build/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,11 @@ var BuildCmd = &cobra.Command{

err = bgit.Add("bsf/")
if err != nil {
if err == bgit.ErrFilesNotAddedToVersionControl{
fmt.Println(styles.ErrorStyle.Render(err.Error() + "\n Please ensure all necessary files are added/committed in your version control system"))
dr-housemd marked this conversation as resolved.
Show resolved Hide resolved
fmt.Println(styles.HintStyle.Render("hint: run git add . "))
os.Exit(1)
}
fmt.Println(styles.ErrorStyle.Render("error: ", err.Error()))
os.Exit(1)
}
Expand Down
30 changes: 29 additions & 1 deletion pkg/git/git.go
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
package git

import (
"errors"
"os"
"path/filepath"
"strings"

"github.com/buildsafedev/bsf/pkg/langdetect"
"github.com/go-git/go-git/v5"
)

var ErrFilesNotAddedToVersionControl = errors.New("files like 'package-lock.json', 'Cargo.lock', 'go.mod', 'poetry.lock' are not added to version control")
Manik2708 marked this conversation as resolved.
Show resolved Hide resolved

// Add adds the path to the git work tree
func Add(path string) error {
var r *git.Repository
Expand Down Expand Up @@ -40,14 +44,38 @@ func Add(path string) error {
if leafDir != "" {
path = leafDir + "/" + path
}

// Add all changes to the working directory
err = w.AddWithOptions(&git.AddOptions{
Path: path,
})
if err != nil {
return err
}
status, err :=w.Status()
if err !=nil{
return err
}
var fileName string
pd, _, err:=langdetect.FindProjectType()
if err!=nil{
return err
}
switch pd{
Manik2708 marked this conversation as resolved.
Show resolved Hide resolved
case langdetect.GoModule:
fileName = "go.mod"
case langdetect.RustCargo:
fileName = "Cargo.lock"
case langdetect.JsNpm:
fileName = "package-lock.json"
case langdetect.PythonPoetry:
fileName = "poetry.lock"
}
fl:= status.File(fileName)
// 63 code represents that file is untracked
// See the StatusCodes of FileStatus for more info
if fl.Staging==63{
return ErrFilesNotAddedToVersionControl
}
return nil
}

Expand Down
240 changes: 240 additions & 0 deletions pkg/git/git_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,240 @@
package git

import (
"os"
"strconv"
"strings"
"testing"

"github.com/go-git/go-git/v5"
)

func getRootDirectory(dir string) string {
arr:= strings.Split(dir, "/")
var indexOfBsf int
for index, value:= range arr {
if value == "bsf"{
indexOfBsf = index
break;
}
}
arr = arr[:indexOfBsf]
str:= strings.Join(arr, "/")
return str
}

func initializeTestEnv(fileName string) (string, string, *os.File, error) {
oldDir, err:= os.Getwd();
newDir:=getRootDirectory(oldDir)
if(err!=nil){
return "","",nil, err
}
os.Mkdir(newDir+"/bsf-temp", 0777)
os.Chdir(newDir+"/bsf-temp")
file, err:=os.Create(fileName)
os.Create("sample.txt")
if err!=nil{
return "","",nil,err
}
// Previous directory is returned so as to return to the project directory
return oldDir, newDir, file, nil
}

func initiateGitEnv() (*git.Worktree, error) {
git.PlainInit(".", false)
r, err := git.PlainOpenWithOptions(".", &git.PlainOpenOptions{DetectDotGit: true})
if err!=nil{
return nil, err
}
w, err := r.Worktree()
if err!=nil{
return nil, err
}
err = w.AddWithOptions(&git.AddOptions{
Path: ".",
})
if err != nil {
return nil, err
}
return w, nil
}

func cleanTestEnv(oldDir string, newDir string) error {
os.RemoveAll(newDir+"/bsf-temp")
os.Chdir(oldDir)
return nil
}


func TestGitAdd(t *testing.T){
t.Run("git.Add() should run without any error for go module", func(t *testing.T) {
oldDir, newDir, file, err:=initializeTestEnv("go.mod")
if err!=nil{
t.Fatal()
}
defer cleanTestEnv(oldDir, newDir)
goContent:=`module test`
file.WriteString(goContent)
initiateGitEnv()
Add("./")
})

tests:=[]struct{
langName string
fileName string
}{
{
langName: "Javascript",
fileName: "package-lock.json",
},
{
langName: "Poetry",
fileName: "poetry.lock",
},
{
langName: "Rust",
fileName: "Cargo.lock",
},
}
for _,tt:= range tests{
testName:= "git.Add() should run without any error for"+ tt.langName
t.Run(testName, func (t *testing.T) {
oldDir, newDir, _, err:=initializeTestEnv(tt.fileName)
if err!=nil{
t.Fatal()
}
defer cleanTestEnv(oldDir, newDir)
initiateGitEnv()
errors:=Add("./")
if errors!=nil{
t.Errorf("want nil but found error: %s", errors.Error())
}
})
}

t.Run("git.Add() should throw error of go.mod not added to version control", func(t *testing.T){
oldDir, newDir, file, err:=initializeTestEnv("go.mod")
if err!=nil{
t.Fatal()
}
defer cleanTestEnv(oldDir, newDir)
goContent:=`module test`
file.WriteString(goContent)
git.PlainInit(".", false)
git.PlainOpenWithOptions(".", &git.PlainOpenOptions{DetectDotGit: true})
errors:= Add("sample.txt")
if errors==nil{
t.Errorf("want error but found nil")
}
if errors != ErrFilesNotAddedToVersionControl{
t.Errorf("want ErrFilesNotAddedToVersionControl but found %s", errors.Error())
}
})

for _,tt:= range tests{
testName:= "git.Add() should throw error of file not added to version control for "+tt.langName
t.Run(testName, func (t *testing.T) {
oldDir, newDir, _, err:=initializeTestEnv(tt.fileName)
if err!=nil{
t.Fatal()
}
defer cleanTestEnv(oldDir, newDir)
git.PlainInit(".", false)
git.PlainOpenWithOptions(".", &git.PlainOpenOptions{DetectDotGit: true})
errors:= Add("sample.txt")
if errors==nil{
t.Errorf("want error but found nil")
}
if errors != ErrFilesNotAddedToVersionControl{
t.Errorf("want ErrFilesNotAddedToVersionControl but found %s", errors.Error())
}
})
}
}

func TestGitIgnore(t *testing.T){
t.Run("git.Ignore() creates .gitignore and adds the path to it", func(t *testing.T) {
oldDir, newDir, _, err:=initializeTestEnv("go.mod")
if err!=nil{
t.Errorf(err.Error())
}
defer cleanTestEnv(oldDir, newDir)
Ignore("sample.txt")
file, err:=os.ReadFile(".gitignore")
if err!=nil{
t.Fatal()
}
want:= strings.Contains(string(file), "sample.txt")
if want==false{
t.Errorf("want true recieved true")
}
})
t.Run("git.Ignore() appends the path in already created .gitignore", func(t *testing.T) {
oldDir, newDir, _, err:=initializeTestEnv("go.mod")
if err!=nil{
t.Errorf(err.Error())
}
defer cleanTestEnv(oldDir, newDir)
fl, err:= os.Create(".gitignore")
if err!=nil{
t.Fatal()
}
fl.WriteString(`
/path/to/be/added/1
/path/to/be/added/2
/path/to/be/added/3
`)
Ignore("sample.txt")
file, err:=os.ReadFile(".gitignore")
if err!=nil{
t.Fatal()
}
want:= strings.Contains(string(file), "sample.txt")
if want==false{
t.Errorf("want true recieved false")
}
for i:=1; i<=3; i++{
want:=strings.Contains(string(file), "/path/to/be/added/"+strconv.Itoa(i))
if want==false{
t.Errorf("want true recieved false")
}
}
})
t.Run("git.Ignore() adds nothing for already added path", func(t *testing.T) {
oldDir, newDir, _, err:=initializeTestEnv("go.mod")
if err!=nil{
t.Errorf(err.Error())
}
defer cleanTestEnv(oldDir, newDir)
fl, err:= os.Create(".gitignore")
if err!=nil{
t.Fatal()
}
fl.WriteString(`
/path/to/be/added/1
/path/to/be/added/2
/path/to/be/added/3
sample.txt
`)
Ignore("sample.txt")
file, err:=os.ReadFile(".gitignore")
if err!=nil{
t.Fatal()
}
want:= strings.Contains(string(file), "sample.txt")
if want==false{
t.Errorf("want true recieved false")
}
for i:=1; i<=3; i++{
want:=strings.Contains(string(file), "/path/to/be/added/"+strconv.Itoa(i))
if want==false{
t.Errorf("want true recieved false")
}
}
count:=strings.Count(string(file), "sample.txt")
if count!=1{
t.Errorf("want count 1 recieved %d", count)
}
})
}

49 changes: 45 additions & 4 deletions pkg/nix/cmd/build.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package cmd

import (
"bufio"
"errors"
"fmt"
"os"
"os/exec"
Expand All @@ -13,10 +15,49 @@ func Build(dir string, attribute string) error {
}
cmd := exec.Command("nix", "build", attribute, "-o", dir)

cmd.Stdout = os.Stdout
// TODO: in future- we can pipe to stderr pipe and modify error messages to be understandable by the user
cmd.Stderr = os.Stderr
stderr, err := cmd.StderrPipe()
if err != nil {
return err
}
stdout, err := cmd.StdoutPipe()
if err != nil {
return err
}
stdErrChan:= make(chan string)
Manik2708 marked this conversation as resolved.
Show resolved Hide resolved

go func(){
scanner:= bufio.NewScanner(stderr)
Manik2708 marked this conversation as resolved.
Show resolved Hide resolved
for scanner.Scan() {
stdErr:= scanner.Text()
dir, err:= os.Getwd()
if err!=nil{
stdErrChan <- err.Error()
}
warning:= fmt.Sprintf("warning: Git tree '%s' is dirty", dir)
if stdErr==warning{
stdErr = fmt.Sprintf("warning: Git tree '%s' is dirty.\nThis implies you have not checked-in files in the git work tree (hint: git add)", dir)
}
stdErr = fmt.Sprint(stdErr, "\n")
os.Stderr.Write([]byte(stdErr))
}
}()

go func(){
scanner:= bufio.NewScanner(stdout)
for scanner.Scan() {
stdOut:= scanner.Text()
stdOut = fmt.Sprint(stdOut, "\n")
os.Stdout.Write([]byte(stdOut))
}
}()

select{
case stdErr:=<-stdErrChan:
return errors.New(stdErr)
default:
break
}

if err := cmd.Start(); err != nil {
return fmt.Errorf("error starting command: %v", err)
}
Expand All @@ -25,4 +66,4 @@ func Build(dir string, attribute string) error {
return fmt.Errorf("error waiting for command: %v", err)
}
return nil
}
}
Loading