44"archive/tar"
55"bytes"
66"io"
7+ "io/fs"
78"os"
89"path/filepath"
910"strings"
@@ -31,43 +32,37 @@ func dirHasExt(dir string, ext string) (bool, error) {
3132return false ,nil
3233}
3334
34- // Tar archives a Terraform directory.
35- func Tar (directory string ,limit int64 ) ([]byte ,error ) {
36- var buffer bytes.Buffer
37- tarWriter := tar .NewWriter (& buffer )
38- totalSize := int64 (0 )
3935
40- const tfExt = ".tf"
41- hasTf ,err := dirHasExt (directory ,tfExt )
42- if err != nil {
43- return nil ,err
44- }
45- if ! hasTf {
46- absPath ,err := filepath .Abs (directory )
47- if err != nil {
48- return nil ,err
49- }
36+ type archiver struct {
5037
51- // Show absolute path to aid in debugging. E.g. showing "." is
52- // useless.
53- return nil ,xerrors .Errorf (
54- "%s is not a valid template since it has no %s files" ,
55- absPath ,tfExt ,
56- )
57- }
38+ }
5839
59- err = filepath . Walk ( directory , func ( file string ,fileInfo os.FileInfo ,err error )error {
40+ func ( a * archiver ) walkFn ( path string ,fileInfo os.FileInfo ,err error )error {
6041if err != nil {
6142return err
6243}
63- var link string
6444if fileInfo .Mode ()& os .ModeSymlink == os .ModeSymlink {
65- link ,err = os .Readlink (file )
45+ // Per https://github.com/coder/coder/issues/5677, we want to
46+ // follow symlinks.
47+ var linkDest string
48+ linkDest ,err = os .Readlink (file )
6649if err != nil {
6750return err
6851}
52+
53+ destInfo ,err := os .Stat (linkDest )
54+ if err != nil {
55+ return err
56+ }
57+ if destInfo .IsDir () {
58+ return filepath .Walk (linkDest ,func (path string ,info fs.FileInfo ,err error )error {
59+ walkFn (path ,info ,err )
60+ })
61+ }
62+ return nil
6963}
70- header ,err := tar .FileInfoHeader (fileInfo ,link )
64+
65+ header ,err := tar .FileInfoHeader (fileInfo ,"" )
7166if err != nil {
7267return err
7368}
@@ -76,11 +71,10 @@ func Tar(directory string, limit int64) ([]byte, error) {
7671return err
7772}
7873if strings .HasPrefix (rel ,"." )|| strings .HasPrefix (filepath .Base (rel ),"." ) {
74+ // Don't archive hidden files!
7975if fileInfo .IsDir ()&& rel != "." {
80- // Don't archive hidden files!
8176return filepath .SkipDir
8277}
83- // Don't archive hidden files!
8478return nil
8579}
8680if strings .Contains (rel ,".tfstate" ) {
@@ -109,7 +103,35 @@ func Tar(directory string, limit int64) ([]byte, error) {
109103return xerrors .Errorf ("Archive too big. Must be <= %d bytes" ,limit )
110104}
111105return data .Close ()
112- })
106+ }
107+ }
108+
109+ // Tar archives a Terraform directory.
110+ func Tar (directory string ,limit int64 ) ([]byte ,error ) {
111+ var buffer bytes.Buffer
112+ tarWriter := tar .NewWriter (& buffer )
113+ totalSize := int64 (0 )
114+
115+ const tfExt = ".tf"
116+ hasTf ,err := dirHasExt (directory ,tfExt )
117+ if err != nil {
118+ return nil ,err
119+ }
120+ if ! hasTf {
121+ absPath ,err := filepath .Abs (directory )
122+ if err != nil {
123+ return nil ,err
124+ }
125+
126+ // Show absolute path to aid in debugging. E.g. showing "." is
127+ // useless.
128+ return nil ,xerrors .Errorf (
129+ "%s is not a valid template since it has no %s files" ,
130+ absPath ,tfExt ,
131+ )
132+ }
133+
134+ err = filepath .Walk (directory ,tarWalkFn ())
113135if err != nil {
114136return nil ,err
115137}