1
+ using System ;
2
+ using System . Collections . Generic ;
3
+ using System . IO ;
4
+ using System . Text ;
5
+ using Avalonia . Markup . Xaml . MarkupExtensions ;
6
+
7
+ namespace GitCredentialManager . Interop . Linux ;
8
+
9
+ public class LinuxSettings : Settings
10
+ {
11
+ private readonly ITrace _trace ;
12
+ private readonly IFileSystem _fs ;
13
+
14
+ private IDictionary < string , string > _extConfigCache ;
15
+
16
+ /// <summary>
17
+ /// Reads settings from Git configuration, environment variables, and defaults from the
18
+ /// /etc/git-credential-manager.d app configuration directory.
19
+ /// </summary>
20
+ public LinuxSettings ( IEnvironment environment , IGit git , ITrace trace , IFileSystem fs )
21
+ : base ( environment , git )
22
+ {
23
+ EnsureArgument . NotNull ( trace , nameof ( trace ) ) ;
24
+ EnsureArgument . NotNull ( fs , nameof ( fs ) ) ;
25
+
26
+ _trace = trace ;
27
+ _fs = fs ;
28
+
29
+ PlatformUtils . EnsureLinux ( ) ;
30
+ }
31
+
32
+ protected internal override bool TryGetExternalDefault ( string section , string scope , string property , out string value )
33
+ {
34
+ value = null ;
35
+
36
+ _extConfigCache ??= ReadExternalConfiguration ( ) ;
37
+
38
+ string name = string . IsNullOrWhiteSpace ( scope )
39
+ ? $ "{ section } .{ property } "
40
+ : $ "{ section } .{ scope } .{ property } ";
41
+
42
+ // Check if the setting exists in the configuration
43
+ if ( ! _extConfigCache ? . TryGetValue ( name , out value ) ?? false )
44
+ {
45
+ // No property exists (or failed to read config)
46
+ return false ;
47
+ }
48
+
49
+ _trace . WriteLine ( $ "Default setting found in app configuration directory: { name } ={ value } ") ;
50
+ return true ;
51
+ }
52
+
53
+ private IDictionary < string , string > ReadExternalConfiguration ( )
54
+ {
55
+ try
56
+ {
57
+ // Check for system-wide config files in /etc/git-credential-manager/config.d and concatenate them together
58
+ // in alphabetical order to form a single configuration.
59
+ const string configDir = Constants . LinuxAppDefaultsDirectoryPath ;
60
+ if ( ! _fs . DirectoryExists ( configDir ) )
61
+ {
62
+ // No configuration directory exists
63
+ return null ;
64
+ }
65
+
66
+ // Get all the files in the configuration directory
67
+ IEnumerable < string > files = _fs . EnumerateFiles ( configDir , "*" ) ;
68
+
69
+ // Read the contents of each file and concatenate them together
70
+ var combinedFile = new StringBuilder ( ) ;
71
+ foreach ( string file in files )
72
+ {
73
+ using Stream stream = _fs . OpenFileStream ( file , FileMode . Open , FileAccess . Read , FileShare . Read ) ;
74
+ using var reader = new StreamReader ( stream ) ;
75
+ string contents = reader . ReadToEnd ( ) ;
76
+ combinedFile . Append ( contents ) ;
77
+ combinedFile . Append ( '\n ' ) ;
78
+ }
79
+
80
+ var parser = new LinuxConfigParser ( _trace ) ;
81
+
82
+ return parser . Parse ( combinedFile . ToString ( ) ) ;
83
+ }
84
+ catch ( Exception ex )
85
+ {
86
+ // Reading defaults is not critical to the operation of the application
87
+ // so we can ignore any errors and just log the failure.
88
+ _trace . WriteLine ( "Failed to read default setting from app configuration directory." ) ;
89
+ _trace . WriteException ( ex ) ;
90
+ return null ;
91
+ }
92
+ }
93
+ }
0 commit comments