diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 80aba40..0e76d72 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -1,5 +1,5 @@ name: Docker -on: push +on: [ push ] jobs: push: @@ -24,13 +24,12 @@ jobs: id: meta uses: docker/metadata-action@v5 with: - # list of Docker images to use as base name for tags + # List of Docker images to use as base name for tags. images: | ${{ github.repository }} - # generate Docker tags based on the following events/attributes + # Generate Docker tags based on the following events/attributes. tags: | type=raw,value=dev - # always generate latest tag on push - name: Build and push to DockerHub id: docker_build diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 7e26b95..d78d3ae 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -26,16 +26,16 @@ jobs: id: meta uses: docker/metadata-action@v5 with: - # list of Docker images to use as base name for tags + # List of Docker images to use as base name for tags. images: | ${{ github.repository }} ghcr.io/${{ github.repository }} - # generate Docker tags based on the following events/attributes + # Generate Docker tags based on the following events/attributes. tags: | type=semver,pattern=v{{version}} type=semver,pattern=v{{major}}.{{minor}} type=semver,pattern=v{{major}} - # always generate latest tag on push + # Always generate latest tag on push. flavor: | latest=true @@ -46,23 +46,4 @@ jobs: push: true tags: ${{ steps.meta.outputs.tags }} build-args: | - VERSION=${{ github.event.release.tag_name }} - - - name: Setup Go Environment - uses: actions/setup-go@v2 - with: - go-version: '^1.20.0' - - - name: Build Binaries - run: | - mkdir -p builds/compressed - go install github.com/mitchellh/gox@latest - cd saveshare - gox --output "../builds/saveshare-{{.OS}}-{{.Arch}}" -osarch 'darwin/amd64 linux/amd64 windows/amd64' - cd ../builds - find . -maxdepth 1 -type f -execdir zip 'compressed/{}.zip' '{}' \; - - - name: Upload Binaries - run: | - go install github.com/tcnksm/ghr@latest - ghr -t ${{ secrets.GITHUB_TOKEN }} --delete Latest builds/compressed/ \ No newline at end of file + VERSION=${{ github.event.release.tag_name }} \ No newline at end of file diff --git a/README.md b/README.md index d982337..09e7a9b 100644 --- a/README.md +++ b/README.md @@ -10,10 +10,6 @@ This is a Dockerized version of the [Satisfactory](https://store.steampowered.com/app/526870/Satisfactory/) dedicated server. -You can alternatively try [saveshare](https://github.com/wolveix/satisfactory-server/tree/main/saveshare) instead (which -relies on -client-hosting). - ### [Experiencing issues? Check our Troubleshooting FAQ wiki!](https://github.com/wolveix/satisfactory-server/wiki/Troubleshooting-FAQ) ## Upgrading for Satisfactory 1.0 diff --git a/saveshare/README.md b/saveshare/README.md index feac461..22a8a38 100755 --- a/saveshare/README.md +++ b/saveshare/README.md @@ -1,6 +1,7 @@ # Satisfactory Save Sharing -**_Note: this is a work in progress. Prior to 1.0's release, the group I played with had been relying on solely this for many months. Now that 1.0 is released, dedicated servers are much more reliable, meaning we haven't really been using SaveShare._** +**_Note: Prior to 1.0's release, the group I played with had been relying on solely this for many months. 1.0's release +drastically improved the stability of dedicated servers, removing the need for SaveShare._** The dedicated server for Satisfactory introduces a few unique bugs to the game, where multiplayer (through joining a friend) doesn't. This application introduces save sharing with friends. It's designed to function similarly to how the @@ -12,7 +13,8 @@ leaves, anyone else can pick up from where they left off. ## Setup -Download the release from the releases tab. When you initially run it, it'll ask for the following information: +Download the last build from [here](https://github.com/wolveix/satisfactory-server/releases/tag/1.8.2). When you +initially run it, it'll ask for the following information: - Server address (IP and port, e.g. `localhost:7790`) - Server password (the SFTP password) diff --git a/saveshare/config.go b/saveshare/config.go index eaf3022..a06548e 100755 --- a/saveshare/config.go +++ b/saveshare/config.go @@ -24,15 +24,13 @@ func NewConfig(configDir string) (*Config, error) { path: configDir + slash + "config.yml", } - // Check if the file exists + // If the file doesn't exist, create an empty file. if _, err := os.Stat(cfg.path); os.IsNotExist(err) { - // If the file doesn't exist, create an empty file if _, err = os.Create(cfg.path); err != nil { return nil, fmt.Errorf("could not create config file: %w", err) } } - // Read the YAML file yamlData, err := os.ReadFile(cfg.path) if err != nil { return nil, fmt.Errorf("could not read config file: %w", err) @@ -42,7 +40,7 @@ func NewConfig(configDir string) (*Config, error) { return nil, fmt.Errorf("could not unmarshal config file: %w", err) } - // populate the blueprint and save paths + // Populate the blueprint and save paths. appDataPath, err := os.UserCacheDir() if err != nil { return nil, fmt.Errorf("could not get appdata path: %w", err) @@ -54,12 +52,11 @@ func NewConfig(configDir string) (*Config, error) { cfg.BlueprintPath = cfg.gamePath + "blueprints" + slash + cfg.SessionName } - // check if the game path exists if _, err = os.Stat(cfg.gamePath); os.IsNotExist(err) { return nil, fmt.Errorf("game path does not exist: %w", err) } - // get the save path + // Determine the save path. if err = filepath.Walk(cfg.gamePath, func(path string, info os.FileInfo, err error) error { if info == nil { return errors.New("path does not exist") diff --git a/saveshare/docker-compose.yml b/saveshare/docker-compose.yml index c8f53be..9ef2b7a 100644 --- a/saveshare/docker-compose.yml +++ b/saveshare/docker-compose.yml @@ -5,5 +5,5 @@ services: volumes: - /opt/saveshare:/home/saveshare/upload ports: - - "15770:22" + - "7790:22" command: saveshare:PASSWORD_HERE:1001 diff --git a/saveshare/go.mod b/saveshare/go.mod index 8ef67f3..867be13 100644 --- a/saveshare/go.mod +++ b/saveshare/go.mod @@ -1,17 +1,17 @@ module github.com/wolveix/satisfactory-server/saveshare -go 1.20 +go 1.22 require ( - github.com/pkg/sftp v1.13.6 - github.com/rs/zerolog v1.30.0 - golang.org/x/crypto v0.17.0 + github.com/pkg/sftp v1.13.7 + github.com/rs/zerolog v1.33.0 + golang.org/x/crypto v0.29.0 gopkg.in/yaml.v3 v3.0.1 ) require ( github.com/kr/fs v0.1.0 // indirect - github.com/mattn/go-colorable v0.1.12 // indirect - github.com/mattn/go-isatty v0.0.14 // indirect - golang.org/x/sys v0.15.0 // indirect + github.com/mattn/go-colorable v0.1.13 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect + golang.org/x/sys v0.27.0 // indirect ) diff --git a/saveshare/go.sum b/saveshare/go.sum index 8975764..4791931 100644 --- a/saveshare/go.sum +++ b/saveshare/go.sum @@ -5,18 +5,20 @@ github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/kr/fs v0.1.0 h1:Jskdu9ieNAYnjxsi0LbQp1ulIKZV1LAFgK1tWhpZgl8= github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= -github.com/mattn/go-colorable v0.1.12 h1:jF+Du6AlPIjs2BiUiQlKOX0rt3SujHxPnksPKZbaA40= -github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= -github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y= -github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/sftp v1.13.6 h1:JFZT4XbOU7l77xGSpOdW+pwIMqP044IyjXX6FGyEKFo= -github.com/pkg/sftp v1.13.6/go.mod h1:tz1ryNURKu77RL+GuCzmoJYxQczL3wLNNpPWagdg4Qk= +github.com/pkg/sftp v1.13.7 h1:uv+I3nNJvlKZIQGSr8JVQLNHFU9YhhNpvC14Y6KgmSM= +github.com/pkg/sftp v1.13.7/go.mod h1:KMKI0t3T6hfA+lTR/ssZdunHo+uwq7ghoN09/FSu3DY= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= -github.com/rs/zerolog v1.30.0 h1:SymVODrcRsaRaSInD9yQtKbtWqwsfoPcRff/oRXLj4c= -github.com/rs/zerolog v1.30.0/go.mod h1:/tk+P47gFdPXq4QYjvCmT5/Gsug2nagsFWBWhAiSi1w= +github.com/rs/zerolog v1.33.0 h1:1cU2KZkvPxNyfgEmhHAz/1A9Bz+llsdYzklWFzgp0r8= +github.com/rs/zerolog v1.33.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= @@ -25,37 +27,49 @@ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw= -golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k= golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= +golang.org/x/crypto v0.29.0 h1:L5SG1JTTXupVV3n6sUqMTeWbjAyfPwoda2DLX8J8FrQ= +golang.org/x/crypto v0.29.0/go.mod h1:+F4F4N5hv6v38hfeYwTdx20oUvLLc+QfrE9Ax9HtgRg= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= +golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= +golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.27.0 h1:wBqf8DvsY9Y/2P8gAfPDEYNuS30J4lPHJxXSb/nJZ+s= +golang.org/x/sys v0.27.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.15.0 h1:y/Oo/a/q3IXu26lQgl04j/gjuBDOBlx7X6Om1j2CPW4= +golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= +golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= +golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0= +golang.org/x/term v0.26.0 h1:WEQa6V3Gja/BhNxg540hBip/kkaYtRg3cxg4oXSw4AU= +golang.org/x/term v0.26.0/go.mod h1:Si5m1o57C5nBNQo5z1iq+XDijt21BDBDp2bK0QI8e3E= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/saveshare/main.go b/saveshare/main.go index 4449071..b474893 100755 --- a/saveshare/main.go +++ b/saveshare/main.go @@ -31,23 +31,22 @@ func main() { logger.Fatal().Err(err).Msg("Failed to create config directory") } - // check if the log file exists, and create it if it doesn't + // Create the log file if it doesn't already exist. if _, err = os.Stat(logfile); os.IsNotExist(err) { if _, err = os.Create(logfile); err != nil { logger.Fatal().Err(err).Msg("Failed to create log file") } } - // open the log file logFile, err := os.OpenFile(logfile, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0o600) if err != nil { logger.Fatal().Err(err).Msg("Failed to open log file") } - // replace the default logger with one that writes to the log file as well as to the console + // Replace the default logger with one that writes a file and to the console. logger = zerolog.New(zerolog.MultiLevelWriter(zerolog.ConsoleWriter{Out: os.Stdout, TimeFormat: time.RFC3339}, logFile)).With().Timestamp().Logger().Level(zerolog.InfoLevel) - logger.Info().Msg("Satisfactory Save Share Client v1.6.1") + logger.Info().Msg("Satisfactory Save Share Client v1.8.2") logger.Info().Msg("https://github.com/wolveix/satisfactory-server/saveshare") logger.Info().Msg("Initializing config...") @@ -100,7 +99,7 @@ func main() { logger.Info().Msg("Config loaded successfully!") - // Establish an SSH connection to the server + // Establish an SSH connection to the server. sshConfig := &ssh.ClientConfig{ User: "saveshare", Auth: []ssh.AuthMethod{ @@ -115,7 +114,7 @@ func main() { } defer sshClient.Close() - // Establish an SFTP session + // Establish an SFTP session. sftpClient, err := sftp.NewClient(sshClient) if err != nil { logger.Fatal().Err(err).Msg("Error creating SFTP client") @@ -127,7 +126,7 @@ func main() { remotePath := "upload/" + cfg.SessionName - // create the remote directories if they don't already exist + // Create the remote directories if they don't already exist. if err = sftpClient.MkdirAll(remotePath + "/blueprints"); err != nil { fmt.Printf("Error creating remote blueprints directory: %v\n", err) return @@ -174,14 +173,14 @@ func syncLocalUpdates(sftpClient *sftp.Client, localPath string, remotePath stri remoteFilePath := remotePath + "/" + info.Name() - // save files are named like: "SESSIONNAME_autosave_0.sav" + // Save files are named like: "SESSIONNAME_autosave_0.sav". if sessionName != "" { if !strings.HasPrefix(info.Name(), sessionName) { return nil } } - // Check if the file exists on the remote server + // Check the file exists on the remote server. remoteFile, err := sftpClient.Stat(remoteFilePath) if err != nil { if os.IsNotExist(err) { @@ -192,7 +191,7 @@ func syncLocalUpdates(sftpClient *sftp.Client, localPath string, remotePath stri } } - // Compare local and remote file timestamps + // Compare local and remote file timestamps. localModTime := info.ModTime().Truncate(1 * time.Second) remoteModTime := remoteFile.ModTime().Truncate(1 * time.Second) @@ -201,11 +200,11 @@ func syncLocalUpdates(sftpClient *sftp.Client, localPath string, remotePath stri } if localModTime.After(remoteModTime) { - // Local file is newer, so upload it + // Local file is newer, so upload it. logger.Info().Msg("Uploading " + localFilePath + " to " + remoteFilePath) return uploadFile(sftpClient, localFilePath, remoteFilePath) } else { - // Remote file is newer, so download it + // Remote file is newer, so download it. logger.Info().Msg("Downloading " + remoteFilePath + " to " + localFilePath) return downloadFile(sftpClient, remoteFilePath, localFilePath) } @@ -213,13 +212,13 @@ func syncLocalUpdates(sftpClient *sftp.Client, localPath string, remotePath stri } func syncRemoteUpdates(sftpClient *sftp.Client, localPath string, remotePath string) error { - // Get a list of files and directories in the remote directory + // Get a list of files and directories from the remote directory. remoteFiles, err := sftpClient.ReadDir(remotePath) if err != nil { return fmt.Errorf("error reading remote directory: %w", err) } - // Iterate through remote files and directories + // Iterate through remote files and directories. for _, remoteFile := range remoteFiles { if remoteFile.IsDir() { return nil @@ -228,11 +227,11 @@ func syncRemoteUpdates(sftpClient *sftp.Client, localPath string, remotePath str localFilePath := localPath + slash + remoteFile.Name() remoteFilePath := remotePath + "/" + remoteFile.Name() - // Check if the file exists on the local side + // Check if the file exists locally. localFile, err := os.Stat(localFilePath) if err != nil { if os.IsNotExist(err) { - // Download the remote file + // Download the remote file. logger.Info().Msg("Downloading " + remoteFilePath + " to " + localFilePath) if err = downloadFile(sftpClient, remoteFilePath, localFilePath); err != nil { return err @@ -244,23 +243,23 @@ func syncRemoteUpdates(sftpClient *sftp.Client, localPath string, remotePath str return fmt.Errorf("error checking local file: %w", err) } - // Compare remote and local file timestamps + // Compare remote and local file timestamps. localModTime := localFile.ModTime().Truncate(1 * time.Second) remoteModTime := remoteFile.ModTime().Truncate(1 * time.Second) - // Compare timestamps and synchronize as needed + // Compare timestamps and synchronize as needed. if localModTime == remoteModTime { continue } if remoteModTime.After(localModTime) { - // Remote file is newer, download it + // Remote file is newer, download it. logger.Info().Msg("Downloading " + remoteFilePath + " to " + localFilePath) if err = downloadFile(sftpClient, remoteFilePath, localFilePath); err != nil { return err } } else { - // Local file is newer, upload it + // Local file is newer, upload it. logger.Info().Msg("Uploading " + localFilePath + " to " + remoteFilePath) if err = uploadFile(sftpClient, localFilePath, remoteFilePath); err != nil { return err