diff --git a/internal/userdirs/config_unix.go b/internal/userdirs/config_unix.go index f6b03b1..ac7efb9 100644 --- a/internal/userdirs/config_unix.go +++ b/internal/userdirs/config_unix.go @@ -11,24 +11,32 @@ import ( "github.com/adrg/xdg/internal/pathutil" ) -// ParseConfigFile parses the user directories config file at the specified -// location. The returned map contains pairs consisting of the user directory -// names and their paths. An empty map is returned if an error is encountered. -func ParseConfigFile(name string) map[string]string { +// ParseConfigFile parses the user directories config file at the +// specified location. +func ParseConfigFile(name string) (*Directories, error) { f, err := os.Open(name) if err != nil { - return map[string]string{} + return nil, err } defer f.Close() return ParseConfig(f) } -// ParseConfig parses the user directories config file contained in the provided -// reader. The returned map contains pairs consisting of the user directory -// names and their paths. An empty map is returned if an error is encountered. -func ParseConfig(r io.Reader) map[string]string { - dirs := map[string]string{} +// ParseConfig parses the user directories config file contained in +// the provided reader. +func ParseConfig(r io.Reader) (*Directories, error) { + dirs := &Directories{} + fieldsMap := map[string]*string{ + EnvDesktopDir: &dirs.Desktop, + EnvDownloadDir: &dirs.Download, + EnvDocumentsDir: &dirs.Documents, + EnvMusicDir: &dirs.Music, + EnvPicturesDir: &dirs.Pictures, + EnvVideosDir: &dirs.Videos, + EnvTemplatesDir: &dirs.Templates, + EnvPublicShareDir: &dirs.PublicShare, + } scanner := bufio.NewScanner(r) for scanner.Scan() { @@ -46,17 +54,8 @@ func ParseConfig(r io.Reader) map[string]string { } // Parse key. - key := strings.TrimSpace(parts[0]) - switch key { - case EnvDesktopDir, - EnvDownloadDir, - EnvDocumentsDir, - EnvMusicDir, - EnvPicturesDir, - EnvVideosDir, - EnvTemplatesDir, - EnvPublicShareDir: - default: + field, ok := fieldsMap[strings.TrimSpace(parts[0])] + if !ok { continue } @@ -70,14 +69,14 @@ func ParseConfig(r io.Reader) map[string]string { for i := 1; i < lenRunes; i++ { if runes[i] == '"' { - dirs[key] = pathutil.ExpandHome(string(runes[1:i])) + *field = pathutil.ExpandHome(string(runes[1:i])) break } } } if err := scanner.Err(); err != nil { - return dirs + return nil, err } - return dirs + return dirs, nil } diff --git a/internal/userdirs/config_unix_test.go b/internal/userdirs/config_unix_test.go index 6f76421..5323119 100644 --- a/internal/userdirs/config_unix_test.go +++ b/internal/userdirs/config_unix_test.go @@ -31,24 +31,26 @@ func TestParseConfigFile(t *testing.T) { err = f.Close() require.NoError(t, err) - dirs := userdirs.ParseConfigFile(f.Name()) + dirs, err := userdirs.ParseConfigFile(f.Name()) + require.NoError(t, err) require.NotNil(t, dirs) - require.Equal(t, "/home/test/Downloads", dirs["XDG_DOWNLOAD_DIR"]) + require.Equal(t, "/home/test/Downloads", dirs.Download) // Test non-existent file. err = os.Remove(f.Name()) require.NoError(t, err) tmpFileRemoved = true - dirs = userdirs.ParseConfigFile(f.Name()) - require.NotNil(t, dirs) + dirs, err = userdirs.ParseConfigFile(f.Name()) + require.Error(t, err) + require.Nil(t, dirs) } func TestParseConfig(t *testing.T) { // Test parsed values. home := pathutil.UserHomeDir() - dirs := userdirs.ParseConfig(strings.NewReader(` + dirs, err := userdirs.ParseConfig(strings.NewReader(` # This file is written by xdg-user-dirs-update # If you want to change or add directories, just edit the line you're # interested in. All local changes will be retained on the next run. @@ -70,15 +72,16 @@ func TestParseConfig(t *testing.T) { XDG_DOWNLOAD_DIR `)) + require.NoError(t, err) require.NotNil(t, dirs) - require.Equal(t, filepath.Join(home, "Desktop"), dirs["XDG_DESKTOP_DIR"]) - require.Equal(t, filepath.Join(home, "Downloads"), dirs["XDG_DOWNLOAD_DIR"]) - require.Equal(t, "/home/test/Templates", dirs["XDG_TEMPLATES_DIR"]) - require.Equal(t, filepath.Join(home, "Public"), dirs["XDG_PUBLICSHARE_DIR"]) - require.Equal(t, filepath.Join(home, "Documents"), dirs["XDG_DOCUMENTS_DIR"]) - require.Equal(t, filepath.Join(home, "Music"), dirs["XDG_MUSIC_DIR"]) - require.Equal(t, "", dirs["XDG_PICTURES_DIR"]) - require.Equal(t, "", dirs["XDG_VIDEOS_DIR"]) + require.Equal(t, filepath.Join(home, "Desktop"), dirs.Desktop) + require.Equal(t, filepath.Join(home, "Downloads"), dirs.Download) + require.Equal(t, "/home/test/Templates", dirs.Templates) + require.Equal(t, filepath.Join(home, "Public"), dirs.PublicShare) + require.Equal(t, filepath.Join(home, "Documents"), dirs.Documents) + require.Equal(t, filepath.Join(home, "Music"), dirs.Music) + require.Equal(t, "", dirs.Pictures) + require.Equal(t, "", dirs.Videos) // Test reader error. f, err := os.CreateTemp("", "test_parse_config") @@ -88,6 +91,7 @@ func TestParseConfig(t *testing.T) { err = f.Close() require.NoError(t, err) - dirs = userdirs.ParseConfig(f) - require.NotNil(t, dirs) + dirs, err = userdirs.ParseConfig(f) + require.Error(t, err) + require.Nil(t, dirs) } diff --git a/paths_unix.go b/paths_unix.go index a87a601..dd98839 100644 --- a/paths_unix.go +++ b/paths_unix.go @@ -52,14 +52,17 @@ func initBaseDirs(home string) { } func initUserDirs(home, configHome string) { - userDirsMap := userdirs.ParseConfigFile(filepath.Join(configHome, "user-dirs.dirs")) + dirs, err := userdirs.ParseConfigFile(filepath.Join(configHome, "user-dirs.dirs")) + if err != nil { + dirs = &UserDirectories{} + } - UserDirs.Desktop = pathutil.EnvPath(userdirs.EnvDesktopDir, userDirsMap[userdirs.EnvDesktopDir], filepath.Join(home, "Desktop")) - UserDirs.Download = pathutil.EnvPath(userdirs.EnvDownloadDir, userDirsMap[userdirs.EnvDownloadDir], filepath.Join(home, "Downloads")) - UserDirs.Documents = pathutil.EnvPath(userdirs.EnvDocumentsDir, userDirsMap[userdirs.EnvDocumentsDir], filepath.Join(home, "Documents")) - UserDirs.Music = pathutil.EnvPath(userdirs.EnvMusicDir, userDirsMap[userdirs.EnvMusicDir], filepath.Join(home, "Music")) - UserDirs.Pictures = pathutil.EnvPath(userdirs.EnvPicturesDir, userDirsMap[userdirs.EnvPicturesDir], filepath.Join(home, "Pictures")) - UserDirs.Videos = pathutil.EnvPath(userdirs.EnvVideosDir, userDirsMap[userdirs.EnvVideosDir], filepath.Join(home, "Videos")) - UserDirs.Templates = pathutil.EnvPath(userdirs.EnvTemplatesDir, userDirsMap[userdirs.EnvTemplatesDir], filepath.Join(home, "Templates")) - UserDirs.PublicShare = pathutil.EnvPath(userdirs.EnvPublicShareDir, userDirsMap[userdirs.EnvPublicShareDir], filepath.Join(home, "Public")) + UserDirs.Desktop = pathutil.EnvPath(userdirs.EnvDesktopDir, dirs.Desktop, filepath.Join(home, "Desktop")) + UserDirs.Download = pathutil.EnvPath(userdirs.EnvDownloadDir, dirs.Download, filepath.Join(home, "Downloads")) + UserDirs.Documents = pathutil.EnvPath(userdirs.EnvDocumentsDir, dirs.Documents, filepath.Join(home, "Documents")) + UserDirs.Music = pathutil.EnvPath(userdirs.EnvMusicDir, dirs.Music, filepath.Join(home, "Music")) + UserDirs.Pictures = pathutil.EnvPath(userdirs.EnvPicturesDir, dirs.Pictures, filepath.Join(home, "Pictures")) + UserDirs.Videos = pathutil.EnvPath(userdirs.EnvVideosDir, dirs.Videos, filepath.Join(home, "Videos")) + UserDirs.Templates = pathutil.EnvPath(userdirs.EnvTemplatesDir, dirs.Templates, filepath.Join(home, "Templates")) + UserDirs.PublicShare = pathutil.EnvPath(userdirs.EnvPublicShareDir, dirs.PublicShare, filepath.Join(home, "Public")) }