Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sensible default folder for log and configuration files #248

Merged
merged 1 commit into from
May 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 26 additions & 24 deletions cmd/shared.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import (
"os"
"runtime"
"strings"
"time"

"github.com/simulot/immich-go/helpers/configuration"
"github.com/simulot/immich-go/helpers/fileevent"
Expand Down Expand Up @@ -46,14 +45,14 @@ type SharedFlags struct {
}

func (app *SharedFlags) InitSharedFlags() {
app.ConfigurationFile = configuration.DefaultFile()
app.ConfigurationFile = configuration.DefaultConfigFile()
app.LogFile = configuration.DefaultLogFile()
app.NoLogColors = runtime.GOOS == "windows"
app.APITrace = false
app.Debug = false
app.SkipSSL = false
app.LogLevel = "INFO"
app.NoUI = false
app.LogFile = "./immich-go " + time.Now().Format("2006-01-02 15-04-05") + ".log"
}

// SetFlag add common flags to a flagset
Expand Down Expand Up @@ -89,31 +88,28 @@ func (app *SharedFlags) Start(ctx context.Context) error {

if app.LogFile != "" {
if app.LogWriterCloser == nil {
err := configuration.MakeDirForFile(app.LogFile)
if err != nil {
return err
}
f, err := os.OpenFile(app.LogFile, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0o664)
if err != nil {
joinedErr = errors.Join(joinedErr, err)
} else {
err = app.Level.UnmarshalText([]byte(strings.ToUpper(app.LogLevel)))
if err != nil {
joinedErr = errors.Join(joinedErr, err)
} else {
app.Log = slog.New(humane.NewHandler(f, &humane.Options{Level: app.Level}))
app.Jnl.SetLogger(app.Log)
}
return err
}
err = app.Level.UnmarshalText([]byte(strings.ToUpper(app.LogLevel)))
if err != nil {
return err
}
app.Log = slog.New(humane.NewHandler(f, &humane.Options{Level: app.Level}))
app.Jnl.SetLogger(app.Log)
app.LogWriterCloser = f
}
}

// at this point, exits if there is an error
if joinedErr != nil {
return joinedErr
}

// If the client isn't yet initialized
if app.Immich == nil {
if app.Server == "" && app.API == "" && app.Key == "" {
conf, err := configuration.Read(app.ConfigurationFile)
conf, err := configuration.ConfigRead(app.ConfigurationFile)
confExist := err == nil
if confExist && app.Server == "" && app.Key == "" && app.API == "" {
app.Server = conf.ServerURL
Expand All @@ -130,6 +126,9 @@ func (app *SharedFlags) Start(ctx context.Context) error {
}
if app.Key == "" {
joinedErr = errors.Join(joinedErr, errors.New("missing -key"))
}

if joinedErr != nil {
return joinedErr
}

Expand All @@ -139,12 +138,15 @@ func (app *SharedFlags) Start(ctx context.Context) error {
APIKey: app.Key,
APIURL: app.API,
}
err := conf.Write(app.ConfigurationFile)
err := configuration.MakeDirForFile(app.ConfigurationFile)
if err != nil {
err = fmt.Errorf("can't write into the configuration file: %w", err)
joinedErr = errors.Join(joinedErr, err)
return joinedErr
return err
}
err = conf.Write(app.ConfigurationFile)
if err != nil {
return fmt.Errorf("can't write into the configuration file: %w", err)
}
app.Log.Info("Connection to the server " + app.Server)

app.Immich, err = immich.NewImmichClient(app.Server, app.Key, app.SkipSSL)
if err != nil {
Expand All @@ -164,13 +166,13 @@ func (app *SharedFlags) Start(ctx context.Context) error {
if err != nil {
return err
}
fmt.Println("Server status: OK")
app.Log.Info("Server status: OK")

user, err := app.Immich.ValidateConnection(ctx)
if err != nil {
return err
}
fmt.Printf("Connected, user: %s\n", user.Email)
app.Log.Info(fmt.Sprintf("Connected, user: %s", user.Email))
}
return nil
}
16 changes: 15 additions & 1 deletion docs/releases.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,22 @@
# Release notes

## Release next

### fix [#215](https://github.com/simulot/immich-go/issues/215) Use XDG_CONFIG_HOME for storing config
The configuration file that contains the server and the key is now stored by default in following folder:
- Linux `$HOME/.config/immich-go/immich-go.json`
- Windows `%AppData%\immich-go\immich-go.json`
- Apple `$HOME/Library/Application Support/immich-go/immich-go.json`

### Store the log files into sensible dir for user's system
The default log file is:
- Linux `$HOME/.cache/immich-go/immich-go_YYYY-MM-DD_HH-MI-SS.log`
- Windows `%LocalAppData%\immich-go\immich-go_YYYY-MM-DD_HH-MI-SS.log`
- Apple `$HOME/Library/Caches/immich-go/immich-go_YYYY-MM-DD_HH-MI-SS.log`

## Release 0.14.1

### [#246](https://github.com/simulot/immich-go/issues/246) Google Takeout 403 Forbidden on non admin user
### fix [#246](https://github.com/simulot/immich-go/issues/246) Google Takeout 403 Forbidden on non admin user
Uses the endpoint /api/asset/statistics to get the number of user's assets.

## Release 0.14.0 "A better UI"
Expand Down
36 changes: 28 additions & 8 deletions helpers/configuration/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"encoding/json"
"os"
"path/filepath"
"time"
)

type Configuration struct {
Expand All @@ -12,18 +13,20 @@ type Configuration struct {
APIKey string
}

// DefaultFile return the default configuration file name
// Return a local file nama when the default UserHomeDir can't be determined,
func DefaultFile() string {
d, err := os.UserHomeDir()
// DefaultConfigFile return the default configuration file name
// Return a local file when the default UserHomeDir can't be determined,
func DefaultConfigFile() string {
config, err := os.UserConfigDir()
if err != nil {
return "immich-go.json"
// $XDG_CONFIG_HOME nor $HOME is set
// return current
return "./immich-go.json"
}
return filepath.Join(d, ".immich-go", "immich-go.json")
return filepath.Join(config, "immich-go", "immich-go.json")
}

// Read the configuration in file name
func Read(name string) (Configuration, error) {
// ConfigRead the configuration in file name
func ConfigRead(name string) (Configuration, error) {
f, err := os.Open(name)
if err != nil {
return Configuration{}, err
Expand Down Expand Up @@ -56,3 +59,20 @@ func (c Configuration) Write(name string) error {
enc.SetIndent("", " ")
return enc.Encode(c)
}

// DefaultLogDir give the default log file
// Return the current dir when $HOME not $XDG_CACHE_HOME are not set
func DefaultLogFile() string {
f := time.Now().Format("immich-go_2006-01-02_15-04-05.log")
d, err := os.UserCacheDir()
if err != nil {
return f
}
return filepath.Join(d, "immich-go", f)
}

// MakeDirForFile create all dirs to write the given file
func MakeDirForFile(f string) error {
dir := filepath.Dir(f)
return os.MkdirAll(dir, 0o700)
}
28 changes: 14 additions & 14 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,19 +57,19 @@ immich-go -server URL -key KEY -general_options COMMAND -command_options... {fil



| **Parameter** | **Description** | **Default value** |
| ---------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------ |
| `-use-configuration=path/to/config/file` | Specifies the configuration file to use. <br>Server URL and the API key are stored into the immich-go configuration file. They can be omitted for the next runs. | `$HOME/.immich-go/immich-go.json` |
| `-server=URL` | URL of the Immich service, example http://<your-ip>:2283 or https://your-domain | |
| `-api=URL` | URL of the Immich api endpoint (http://container_ip:3301) | |
| `-device-uuid=VALUE` | Force the device identification | `$HOSTNAME` |
| `-skip-verify-ssl` | Skip SSL verification for use with self-signed certificates | `false` |
| `-key=KEY` | A key generated by the user. Uploaded photos will belong to the key's owner. | |
| `-no-colors-log` | Remove color codes from logs. | `TRUE` on Windows, `FALSE` otherwise |
| `-log-level=LEVEL` | Adjust the log verbosity as follows: <br> - `ERROR`: Display only errors <br> - `WARNING`: Same as previous one plus non blocking error <br> - `INFO`: Information messages | `INFO` |
| `-log-file=/path/to/log/file` | Write all messages to a file | `immich-go YYYY-MM-DD HH-MI-SS.log` |
| `-time-zone=time_zone_name` | Set the time zone for dates without time zone information | the system's time zone |
| `-no-ui` | Disable the user interface | 'false' |
| **Parameter** | **Description** | **Default value** |
| ---------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------- |
| `-use-configuration=path/to/config/file` | Specifies the configuration file to use. <br>Server URL and the API key are stored into the immich-go configuration file. They can be omitted for the next runs. | Linux `$HOME/.config/immich-go/immich-go.json`<br>Windows `%AppData%\immich-go\immich-go.json`<br>Apple `$HOME/Library/Application Support/immich-go/immich-go.json` |
| `-server=URL` | URL of the Immich service, example http://<your-ip>:2283 or https://your-domain | |
| `-api=URL` | URL of the Immich api endpoint (http://container_ip:3301) | |
| `-device-uuid=VALUE` | Force the device identification | `$HOSTNAME` |
| `-skip-verify-ssl` | Skip SSL verification for use with self-signed certificates | `false` |
| `-key=KEY` | A key generated by the user. Uploaded photos will belong to the key's owner. | |
| `-no-colors-log` | Remove color codes from logs. | `TRUE` on Windows, `FALSE` otherwise |
| `-log-level=LEVEL` | Adjust the log verbosity as follows: <br> - `ERROR`: Display only errors <br> - `WARNING`: Same as previous one plus non blocking error <br> - `INFO`: Information messages | `INFO` |
| `-log-file=/path/to/log/file` | Write all messages to a file | Linux `$HOME/.cache/immich-go/immich-go_YYYY-MM-DD_HH-MI-SS.log` <br>Windows `%LocalAppData%\immich-go\immich-go_YYYY-MM-DD_HH-MI-SS.log` <br>Apple `$HOME/Library/Caches/immich-go/immich-go_YYYY-MM-DD_HH-MI-SS.log`|
| `-time-zone=time_zone_name` | Set the time zone for dates without time zone information | the system's time zone |
| `-no-ui` | Disable the user interface | 'false' |


## Command `upload`
Expand All @@ -82,7 +82,7 @@ Use this command for uploading photos and videos from a local directory, a zippe
| ------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------- |
| `-album="ALBUM NAME"` | Import assets into the Immich album `ALBUM NAME`. | |
| `-dry-run` | Preview all actions as they would be done. | `FALSE` |
| `-create-album-folder` | Generate immich albums after folder names. | `FALSE` |
| `-create-album-folder` | Generate immich albums after folder names. | `FALSE` |
| `-force-sidecar ` | Force sending a .xmp sidecar file beside images. With Google photos date and GPS coordinates are taken from metadata.json files to creates an XMP file and. | `FALSE` |
| `-create-stacks` | Stack jpg/raw or bursts. | `TRUE` |
| `-stack-jpg-raw` | Control the stacking of jpg/raw photos. | `TRUE` |
Expand Down