diff --git a/internal/resolution/pm/pip/job.go b/internal/resolution/pm/pip/job.go index d233b5af..09229654 100644 --- a/internal/resolution/pm/pip/job.go +++ b/internal/resolution/pm/pip/job.go @@ -214,6 +214,7 @@ func (j *Job) getCouldNotFindVersionErrorDocumentation(cmdError job.IError) stri func (j *Job) writeLockContent() job.IError { status := "generating lock file" + var replacer = strings.NewReplacer("\r\n", "\n") // replace CRLF (Windows newline) with just LF (Unix newline) j.SendStatus(status) catCmdOutput, cmdErr := j.runCatCmd() if cmdErr != nil { @@ -248,16 +249,20 @@ func (j *Job) writeLockContent() job.IError { defer closeFile(j, lockFile) var fileContents []string - fileContents = append(fileContents, string(catCmdOutput)) + fileContents = append(fileContents, replacer.Replace(string(catCmdOutput))) fileContents = append(fileContents, lockFileDelimiter) - fileContents = append(fileContents, string(listCmdOutput)) + fileContents = append(fileContents, replacer.Replace(string(listCmdOutput))) fileContents = append(fileContents, lockFileDelimiter) - fileContents = append(fileContents, string(ShowCmdOutput)) + fileContents = append(fileContents, replacer.Replace(string(ShowCmdOutput))) + res := []byte(strings.Join(fileContents, "\n")) status = "writing lock file" j.SendStatus(status) - err = j.fileWriter.Write(lockFile, res) + err = j.fileWriter.Write( + lockFile, + res, + ) if err != nil { cmdErr = util.NewPMJobError(err.Error()) cmdErr.SetStatus(status) diff --git a/internal/resolution/pm/pip/job_test.go b/internal/resolution/pm/pip/job_test.go index d5a5b4a4..af2e8720 100644 --- a/internal/resolution/pm/pip/job_test.go +++ b/internal/resolution/pm/pip/job_test.go @@ -280,6 +280,20 @@ func TestRun(t *testing.T) { assert.Equal(t, string(res), string(fileWriterMock.Contents)) } +func TestRunCRLFFiles(t *testing.T) { + + fileWriterMock := &writerTestdata.FileWriterMock{} + cmdFactoryMock := testdata.NewCRLFEchoCmdFactory() + j := NewJob("file", true, cmdFactoryMock, fileWriterMock, pipCleaner{}) + + go jobTestdata.WaitStatus(j) + j.Run() + + assert.False(t, j.Errors().HasError()) + fmt.Println(string(fileWriterMock.Contents)) + assert.False(t, strings.Contains(string(fileWriterMock.Contents), "\r\n")) +} + func TestRunInstall(t *testing.T) { cmdFactoryMock := testdata.NewEchoCmdFactory() fileWriterMock := &writerTestdata.FileWriterMock{} diff --git a/internal/resolution/pm/pip/testdata/crlf_cmd_factory_mock.go b/internal/resolution/pm/pip/testdata/crlf_cmd_factory_mock.go new file mode 100644 index 00000000..b35742c0 --- /dev/null +++ b/internal/resolution/pm/pip/testdata/crlf_cmd_factory_mock.go @@ -0,0 +1,48 @@ +package testdata + +import ( + "os/exec" +) + +type CmdFactoryMockCRLF struct { + CreateVenvCmdName string + MakeCreateVenvErr error + InstallCmdName string + MakeInstallErr error + CatCmdName string + MakeCatErr error + ListCmdName string + MakeListErr error + ShowCmdName string + MakeShowErr error +} + +func NewCRLFEchoCmdFactory() CmdFactoryMockCRLF { + return CmdFactoryMockCRLF{ + CreateVenvCmdName: "echo", + InstallCmdName: "echo", + CatCmdName: "echo", + ListCmdName: "echo", + ShowCmdName: "echo", + } +} + +func (f CmdFactoryMockCRLF) MakeCreateVenvCmd(file string) (*exec.Cmd, error) { + return exec.Command(f.CreateVenvCmdName, file), f.MakeCreateVenvErr +} + +func (f CmdFactoryMockCRLF) MakeInstallCmd(command string, file string) (*exec.Cmd, error) { + return exec.Command(f.InstallCmdName, file), f.MakeInstallErr +} + +func (f CmdFactoryMockCRLF) MakeListCmd(command string) (*exec.Cmd, error) { + return exec.Command(f.ListCmdName, "Package Version Editable project location\r\n----------------------------- ------------ ------------------------------------------------------\r\nFlask 2.0.3"), f.MakeListErr +} + +func (f CmdFactoryMockCRLF) MakeCatCmd(file string) (*exec.Cmd, error) { + return exec.Command(f.CatCmdName, "Flask==2.1.5\r\n"), f.MakeCatErr +} + +func (f CmdFactoryMockCRLF) MakeShowCmd(command string, list []string) (*exec.Cmd, error) { + return exec.Command(f.ShowCmdName, "Name: Flask\r\nVersion: 2.1.2\r\nSummary: A simple framework for building complex web applications.\r\nHome-page: https://palletsprojects.com/p/flask\r\nAuthor: Armin Ronacher\r\nAuthor-email: armin.ronacher@active-4.com\r\nLicense: BSD-3-Clause\r\nLocation: /path/to/site-packages\r\nRequires: click, importlib-metadata, itsdangerous, Jinja2, Werkzeug\r\nRequired-by: Flask-Script, Flask-Compress, Flask-Bcrypt\r\n"), f.MakeShowErr +}