github.com/mutagen-io/mutagen@v0.18.0-rc1/pkg/filesystem/mutagen.go (about) 1 package filesystem 2 3 import ( 4 "errors" 5 "fmt" 6 "os" 7 "path/filepath" 8 9 "github.com/mutagen-io/mutagen/pkg/mutagen" 10 ) 11 12 const ( 13 // MutagenDataDirectoryName is the name of the global Mutagen data directory 14 // inside the user's home directory. 15 MutagenDataDirectoryName = ".mutagen" 16 17 // MutagenDataDirectoryDevelopmentName is the name of the global Mutagen 18 // data directory inside the user's home directory for development builds of 19 // Mutagen. 20 MutagenDataDirectoryDevelopmentName = ".mutagen-dev" 21 22 // MutagenGlobalConfigurationName is the name of the global Mutagen 23 // configuration file inside the user's home directory. 24 MutagenGlobalConfigurationName = ".mutagen.yml" 25 26 // MutagenDaemonDirectoryName is the name of the daemon storage directory 27 // within the Mutagen data directory. 28 MutagenDaemonDirectoryName = "daemon" 29 30 // MutagenAgentsDirectoryName is the name of the agent storage directory 31 // within the Mutagen data directory. 32 MutagenAgentsDirectoryName = "agents" 33 34 // MutagenSynchronizationSessionsDirectoryName is the name of the 35 // synchronization session storage directory within the Mutagen data 36 // directory. 37 MutagenSynchronizationSessionsDirectoryName = "sessions" 38 39 // MutagenSynchronizationCachesDirectoryName is the name of the 40 // synchronization cache storage directory within the Mutagen data 41 // directory. 42 MutagenSynchronizationCachesDirectoryName = "caches" 43 44 // MutagenSynchronizationArchivesDirectoryName is the name of the 45 // synchronization archive storage directory within the Mutagen data 46 // directory. 47 MutagenSynchronizationArchivesDirectoryName = "archives" 48 49 // MutagenSynchronizationStagingDirectoryName is the name of the 50 // synchronization staging storage directory within the Mutagen data 51 // directory. 52 MutagenSynchronizationStagingDirectoryName = "staging" 53 54 // MutagenForwardingDirectoryName is the name of the forwarding data 55 // directory within the Mutagen data directory. 56 MutagenForwardingDirectoryName = "forwarding" 57 58 // MutagenIODirectoryName is the name of the mutagen.io data directory 59 // within the Mutagen data directory. This directory is no longer used. It 60 // was originally added to support the tunnel transport, but that no longer 61 // exists. This constant is left in-place as a reminder to avoid using this 62 // particular name for future functionality (at least without taking care to 63 // avoid collision with any existing files). 64 MutagenIODirectoryName = "mutagen.io" 65 66 // MutagenLicensingDirectoryName is the name of the licensing data directory 67 // within the Mutagen data directory. 68 MutagenLicensingDirectoryName = "licensing" 69 ) 70 71 // Mutagen computes (and optionally creates) subdirectories inside the Mutagen 72 // data directory. 73 func Mutagen(create bool, pathComponents ...string) (string, error) { 74 // Check if a data directory path has been explicitly specified. If not, 75 // compute it using the standard procedure. Also track whether or not we 76 // need to mark the directory as hidden on creation. 77 mutagenDataDirectoryPath, ok := os.LookupEnv("MUTAGEN_DATA_DIRECTORY") 78 var hide bool 79 if ok { 80 // Validate the provided path. 81 if mutagenDataDirectoryPath == "" { 82 return "", errors.New("provided data directory path is empty") 83 } else if !filepath.IsAbs(mutagenDataDirectoryPath) { 84 return "", errors.New("provided data directory path is not absolute") 85 } 86 } else { 87 // Compute the path to the user's home directory. 88 homeDirectory, err := os.UserHomeDir() 89 if err != nil { 90 return "", fmt.Errorf("unable to compute path to home directory: %w", err) 91 } 92 93 // Compute the path to the Mutagen data directory. 94 if !mutagen.DevelopmentModeEnabled { 95 mutagenDataDirectoryPath = filepath.Join(homeDirectory, MutagenDataDirectoryName) 96 } else { 97 mutagenDataDirectoryPath = filepath.Join(homeDirectory, MutagenDataDirectoryDevelopmentName) 98 } 99 100 // Flag the directory for hiding. 101 hide = true 102 } 103 104 // Compute the target path. 105 result := filepath.Join(mutagenDataDirectoryPath, filepath.Join(pathComponents...)) 106 107 // Handle directory creation, if requested. 108 // 109 // TODO: Should we iterate through each component and ensure the user hasn't 110 // changed the directory permissions? MkdirAll won't reset them. But I 111 // suppose the user may have changed them for whatever reason (though I 112 // can't imagine any). 113 if create { 114 // Create the directory. 115 if err := os.MkdirAll(result, 0700); err != nil { 116 return "", fmt.Errorf("unable to create subpath: %w", err) 117 } 118 119 // Mark the directory as hidden, if necessary. 120 if hide { 121 if err := MarkHidden(mutagenDataDirectoryPath); err != nil { 122 return "", fmt.Errorf("unable to hide Mutagen data directory: %w", err) 123 } 124 } 125 } 126 127 // Success. 128 return result, nil 129 }