Skip to content

Commit c59ccec

Browse files
committed
Print symlink in the baseline
1 parent 6769625 commit c59ccec

File tree

3 files changed

+76
-29
lines changed

3 files changed

+76
-29
lines changed

internal/execute/testsys_test.go

Lines changed: 29 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import (
2020
"github.com/microsoft/typescript-go/internal/testutil/stringtestutil"
2121
"github.com/microsoft/typescript-go/internal/tsoptions"
2222
"github.com/microsoft/typescript-go/internal/vfs"
23+
"github.com/microsoft/typescript-go/internal/vfs/iovfs"
2324
"github.com/microsoft/typescript-go/internal/vfs/vfstest"
2425
)
2526

@@ -96,9 +97,10 @@ func newTestSys(tscInput *tscInput) *testSys {
9697
}
9798

9899
type diffEntry struct {
99-
content string
100-
mTime time.Time
101-
isWritten bool
100+
content string
101+
mTime time.Time
102+
isWritten bool
103+
symlinkTarget string
102104
}
103105

104106
type snapshot struct {
@@ -139,8 +141,8 @@ func (s *testSys) testFs() *testFs {
139141
return s.fs.FS.(*testFs)
140142
}
141143

142-
func (s *testSys) fsFromFileMap() vfs.FS {
143-
return s.testFs().FS
144+
func (s *testSys) fsFromFileMap() iovfs.FsWithSys {
145+
return s.testFs().FS.(iovfs.FsWithSys)
144146
}
145147

146148
func (s *testSys) ensureLibPathExists(path string) {
@@ -316,7 +318,23 @@ func (s *testSys) baselineFSwithDiff(baseline io.Writer) {
316318
return e
317319
}
318320

319-
if !d.Type().IsRegular() {
321+
fileInfo := d.Type()
322+
if fileInfo&fs.ModeSymlink != 0 {
323+
target, ok := s.fsFromFileMap().FSys().(*vfstest.MapFS).GetTargetOfSymlink(path)
324+
if !ok {
325+
panic("Failed to resolve symlink target: " + path)
326+
}
327+
stat := s.fsFromFileMap().Stat(path)
328+
if stat == nil {
329+
panic("stat is nil: " + path)
330+
}
331+
newEntry := &diffEntry{symlinkTarget: target, mTime: stat.ModTime()}
332+
snap[path] = newEntry
333+
s.addFsEntryDiff(diffs, newEntry, path)
334+
return nil
335+
}
336+
337+
if !fileInfo.IsRegular() {
320338
return nil
321339
}
322340

@@ -376,7 +394,11 @@ func (s *testSys) addFsEntryDiff(diffs map[string]string, newDirContent *diffEnt
376394
// todo handle more cases of fs changes
377395
if oldDirContent == nil {
378396
if s.testFs().defaultLibs == nil || !s.testFs().defaultLibs.Has(path) {
379-
diffs[path] = "*new* \n" + newDirContent.content
397+
if newDirContent.symlinkTarget != "" {
398+
diffs[path] = "-> " + newDirContent.symlinkTarget + " *new*"
399+
} else {
400+
diffs[path] = "*new* \n" + newDirContent.content
401+
}
380402
}
381403
} else if newDirContent == nil {
382404
diffs[path] = "*deleted*"

internal/vfs/iovfs/iofs.go

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,11 @@ type WritableFS interface {
2626
Chtimes(path string, aTime time.Time, mTime time.Time) error
2727
}
2828

29+
type FsWithSys interface {
30+
vfs.FS
31+
FSys() fs.FS
32+
}
33+
2934
// From creates a new FS from an [fs.FS].
3035
//
3136
// For paths like `c:/foo/bar`, fsys will be used as though it's rooted at `/` and the path is `/c:/foo/bar`.
@@ -35,7 +40,7 @@ type WritableFS interface {
3540
//
3641
// From does not actually handle case-insensitivity; ensure the passed in [fs.FS]
3742
// respects case-insensitive file names if needed. Consider using [vfstest.FromMap] for testing.
38-
func From(fsys fs.FS, useCaseSensitiveFileNames bool) vfs.FS {
43+
func From(fsys fs.FS, useCaseSensitiveFileNames bool) FsWithSys {
3944
var realpath func(path string) (string, error)
4045
if fsys, ok := fsys.(RealpathFS); ok {
4146
realpath = func(path string) (string, error) {
@@ -118,6 +123,7 @@ func From(fsys fs.FS, useCaseSensitiveFileNames bool) vfs.FS {
118123
mkdirAll: mkdirAll,
119124
remove: remove,
120125
chtimes: chtimes,
126+
fsys: fsys,
121127
}
122128
}
123129

@@ -130,9 +136,10 @@ type ioFS struct {
130136
mkdirAll func(path string) error
131137
remove func(path string) error
132138
chtimes func(path string, aTime time.Time, mTime time.Time) error
139+
fsys fs.FS
133140
}
134141

135-
var _ vfs.FS = (*ioFS)(nil)
142+
var _ FsWithSys = (*ioFS)(nil)
136143

137144
func (vfs *ioFS) UseCaseSensitiveFileNames() bool {
138145
return vfs.useCaseSensitiveFileNames
@@ -194,3 +201,7 @@ func (vfs *ioFS) WriteFile(path string, content string, writeByteOrderMark bool)
194201
}
195202
return vfs.writeFile(path, content, writeByteOrderMark)
196203
}
204+
205+
func (vfs *ioFS) FSys() fs.FS {
206+
return vfs.fsys
207+
}

internal/vfs/vfstest/vfstest.go

Lines changed: 34 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import (
1717
"github.com/microsoft/typescript-go/internal/vfs/iovfs"
1818
)
1919

20-
type mapFS struct {
20+
type MapFS struct {
2121
// mu protects m.
2222
// A single mutex is sufficient as we only use fstest.Map's Open method.
2323
mu sync.RWMutex
@@ -53,8 +53,8 @@ func (t *Time) SinceStart() time.Duration {
5353
}
5454

5555
var (
56-
_ iovfs.RealpathFS = (*mapFS)(nil)
57-
_ iovfs.WritableFS = (*mapFS)(nil)
56+
_ iovfs.RealpathFS = (*MapFS)(nil)
57+
_ iovfs.WritableFS = (*MapFS)(nil)
5858
)
5959

6060
type sys struct {
@@ -79,7 +79,7 @@ func FromMap[File any](m map[string]File, useCaseSensitiveFileNames bool) vfs.FS
7979
// The paths must be normalized absolute paths according to the tspath package,
8080
// without trailing directory separators.
8181
// The paths must be all POSIX-style or all Windows-style, but not both.
82-
func FromMapWithTime[File any](m map[string]File, useCaseSensitiveFileNames bool) (vfs.FS, *Time) {
82+
func FromMapWithTime[File any](m map[string]File, useCaseSensitiveFileNames bool) (iovfs.FsWithSys, *Time) {
8383
posix := false
8484
windows := false
8585
timeImpl := &Time{start: time.Now()}
@@ -142,8 +142,8 @@ func FromMapWithTime[File any](m map[string]File, useCaseSensitiveFileNames bool
142142
return iovfs.From(convertMapFS(mfs, useCaseSensitiveFileNames, timeImpl), useCaseSensitiveFileNames), timeImpl
143143
}
144144

145-
func convertMapFS(input fstest.MapFS, useCaseSensitiveFileNames bool, timeImpl *Time) *mapFS {
146-
m := &mapFS{
145+
func convertMapFS(input fstest.MapFS, useCaseSensitiveFileNames bool, timeImpl *Time) *MapFS {
146+
m := &MapFS{
147147
m: make(fstest.MapFS, len(input)),
148148
useCaseSensitiveFileNames: useCaseSensitiveFileNames,
149149
timeImpl: timeImpl,
@@ -202,15 +202,15 @@ func comparePathsByParts(a, b string) int {
202202

203203
type canonicalPath string
204204

205-
func (m *mapFS) getCanonicalPath(p string) canonicalPath {
205+
func (m *MapFS) getCanonicalPath(p string) canonicalPath {
206206
return canonicalPath(tspath.GetCanonicalFileName(p, m.useCaseSensitiveFileNames))
207207
}
208208

209-
func (m *mapFS) open(p canonicalPath) (fs.File, error) {
209+
func (m *MapFS) open(p canonicalPath) (fs.File, error) {
210210
return m.m.Open(string(p))
211211
}
212212

213-
func (m *mapFS) remove(path string) error {
213+
func (m *MapFS) remove(path string) error {
214214
canonical := m.getCanonicalPath(path)
215215
canonicalString := string(canonical)
216216
fileInfo := m.m[canonicalString]
@@ -240,7 +240,7 @@ func Symlink(target string) *fstest.MapFile {
240240
}
241241
}
242242

243-
func (m *mapFS) getFollowingSymlinks(p canonicalPath) (*fstest.MapFile, canonicalPath, error) {
243+
func (m *MapFS) getFollowingSymlinks(p canonicalPath) (*fstest.MapFile, canonicalPath, error) {
244244
return m.getFollowingSymlinksWorker(p, "", "")
245245
}
246246

@@ -252,7 +252,7 @@ func (e *brokenSymlinkError) Error() string {
252252
return fmt.Sprintf("broken symlink %q -> %q", e.from, e.to)
253253
}
254254

255-
func (m *mapFS) getFollowingSymlinksWorker(p canonicalPath, symlinkFrom, symlinkTo canonicalPath) (*fstest.MapFile, canonicalPath, error) {
255+
func (m *MapFS) getFollowingSymlinksWorker(p canonicalPath, symlinkFrom, symlinkTo canonicalPath) (*fstest.MapFile, canonicalPath, error) {
256256
if file, ok := m.m[string(p)]; ok && file.Mode&fs.ModeSymlink == 0 {
257257
return file, p, nil
258258
}
@@ -275,11 +275,11 @@ func (m *mapFS) getFollowingSymlinksWorker(p canonicalPath, symlinkFrom, symlink
275275
return nil, p, err
276276
}
277277

278-
func (m *mapFS) set(p canonicalPath, file *fstest.MapFile) {
278+
func (m *MapFS) set(p canonicalPath, file *fstest.MapFile) {
279279
m.m[string(p)] = file
280280
}
281281

282-
func (m *mapFS) setEntry(realpath string, canonical canonicalPath, file fstest.MapFile) {
282+
func (m *MapFS) setEntry(realpath string, canonical canonicalPath, file fstest.MapFile) {
283283
if realpath == "" || canonical == "" {
284284
panic("empty path")
285285
}
@@ -316,7 +316,7 @@ func baseName(p string) string {
316316
return file
317317
}
318318

319-
func (m *mapFS) mkdirAll(p string, perm fs.FileMode) error {
319+
func (m *MapFS) mkdirAll(p string, perm fs.FileMode) error {
320320
if p == "" {
321321
panic("empty path")
322322
}
@@ -419,7 +419,7 @@ func (f *readDirFile) ReadDir(n int) ([]fs.DirEntry, error) {
419419
return entries, nil
420420
}
421421

422-
func (m *mapFS) Open(name string) (fs.File, error) {
422+
func (m *MapFS) Open(name string) (fs.File, error) {
423423
m.mu.RLock()
424424
defer m.mu.RUnlock()
425425

@@ -461,7 +461,7 @@ func (m *mapFS) Open(name string) (fs.File, error) {
461461
}, nil
462462
}
463463

464-
func (m *mapFS) Realpath(name string) (string, error) {
464+
func (m *MapFS) Realpath(name string) (string, error) {
465465
m.mu.RLock()
466466
defer m.mu.RUnlock()
467467

@@ -486,14 +486,14 @@ func convertInfo(info fs.FileInfo) (*fileInfo, bool) {
486486

487487
const umask = 0o022
488488

489-
func (m *mapFS) MkdirAll(path string, perm fs.FileMode) error {
489+
func (m *MapFS) MkdirAll(path string, perm fs.FileMode) error {
490490
m.mu.Lock()
491491
defer m.mu.Unlock()
492492

493493
return m.mkdirAll(path, perm)
494494
}
495495

496-
func (m *mapFS) WriteFile(path string, data []byte, perm fs.FileMode) error {
496+
func (m *MapFS) WriteFile(path string, data []byte, perm fs.FileMode) error {
497497
m.mu.Lock()
498498
defer m.mu.Unlock()
499499

@@ -530,14 +530,14 @@ func (m *mapFS) WriteFile(path string, data []byte, perm fs.FileMode) error {
530530
return nil
531531
}
532532

533-
func (m *mapFS) Remove(path string) error {
533+
func (m *MapFS) Remove(path string) error {
534534
m.mu.Lock()
535535
defer m.mu.Unlock()
536536

537537
return m.remove(path)
538538
}
539539

540-
func (m *mapFS) Chtimes(path string, aTime time.Time, mTime time.Time) error {
540+
func (m *MapFS) Chtimes(path string, aTime time.Time, mTime time.Time) error {
541541
m.mu.Lock()
542542
defer m.mu.Unlock()
543543
canonical := m.getCanonicalPath(path)
@@ -551,6 +551,20 @@ func (m *mapFS) Chtimes(path string, aTime time.Time, mTime time.Time) error {
551551
return nil
552552
}
553553

554+
func (m *MapFS) GetTargetOfSymlink(path string) (string, bool) {
555+
path, _ = strings.CutPrefix(path, "/")
556+
m.mu.RLock()
557+
defer m.mu.RUnlock()
558+
canonical := m.getCanonicalPath(path)
559+
canonicalString := string(canonical)
560+
if fileInfo, ok := m.m[canonicalString]; ok {
561+
if fileInfo.Mode&fs.ModeSymlink != 0 {
562+
return "/" + string(fileInfo.Data), true
563+
}
564+
}
565+
return "", false
566+
}
567+
554568
func must[T any](v T, err error) T {
555569
if err != nil {
556570
panic(err)

0 commit comments

Comments
 (0)