Skip to content
go-libfossil Artifact [aea46ccf5f]
Login

Artifact [aea46ccf5f]

Artifact aea46ccf5f4bc66699024225c638e752d3e3cf5e2339ac46e17ad006c116d2c8:


//go:build unix

package undo_test

import (
	"os"
	"path/filepath"
	"testing"

	"github.com/danmestas/go-libfossil/internal/undo"
	"github.com/danmestas/go-libfossil/internal/vfile"
	"github.com/danmestas/go-libfossil/simio"
)

// RestoreFiles puts a symlink ReadFile saw back as a symlink, deleting what
// replaced it rather than writing through it, as fossil's undo_rollback
// does; with allow-symlinks off the link is read and written through, as
// fossil's RepoFILE then follows it.
func TestRestoreFilesRestoresSymlink(t *testing.T) {
	dir := t.TempDir()
	link := filepath.Join(dir, "link")
	for name, body := range map[string]string{"plain.txt": "plain\n", "other.txt": "other\n"} {
		if err := os.WriteFile(filepath.Join(dir, name), []byte(body), 0o644); err != nil {
			t.Fatal(err)
		}
	}
	if err := os.Symlink("plain.txt", link); err != nil {
		t.Fatal(err)
	}
	disk := vfile.NewDisk(simio.RealEnv(), true)
	f, err := undo.ReadFile(disk, dir, "link")
	if err != nil {
		t.Fatal(err)
	}
	if err := os.Remove(link); err != nil {
		t.Fatal(err)
	}
	if err := os.Symlink("other.txt", link); err != nil {
		t.Fatal(err)
	}
	if err := undo.RestoreFiles(disk, dir, []undo.File{f}); err != nil {
		t.Fatal(err)
	}
	if got, err := os.Readlink(link); err != nil || got != "plain.txt" {
		t.Fatalf("link: Readlink = %q, %v; want a symlink to plain.txt", got, err)
	}
	for name, body := range map[string]string{"plain.txt": "plain\n", "other.txt": "other\n"} {
		if data, err := os.ReadFile(filepath.Join(dir, name)); err != nil || string(data) != body {
			t.Fatalf("%s = %q, %v; want %q", name, data, err, body)
		}
	}

	off := vfile.NewDisk(simio.RealEnv(), false)
	if f, err = undo.ReadFile(off, dir, "link"); err != nil {
		t.Fatal(err)
	}
	if err := os.WriteFile(link, []byte("edited\n"), 0o644); err != nil {
		t.Fatal(err)
	}
	if err := undo.RestoreFiles(off, dir, []undo.File{f}); err != nil {
		t.Fatal(err)
	}
	if got, err := os.Readlink(link); err != nil || got != "plain.txt" {
		t.Fatalf("link with allow-symlinks off: Readlink = %q, %v; want it kept", got, err)
	}
	if data, err := os.ReadFile(filepath.Join(dir, "plain.txt")); err != nil || string(data) != "plain\n" {
		t.Fatalf("plain.txt = %q, %v; want its saved content back", data, err)
	}
}