99using Installer . ViewModels ;
1010using Avalonia . Controls ;
1111using System . Collections . Generic ;
12+ using LibGit2Sharp ;
13+ using System . Net ;
14+ using System . Linq ;
1215
1316namespace Installer ;
1417
@@ -25,7 +28,7 @@ public static class Installation
2528 private static Action ? _markErrored ;
2629 private static bool _errored = false ;
2730 private static string _path = "" ;
28- private static string _latestTag = "" ;
31+ private static Tag ? _latestTag ;
2932
3033 public static async Task InstallRbxcs (
3134 Action < int > updateProgress ,
@@ -69,37 +72,102 @@ string path
6972 ShowErrorMessageBox ( $ "Failed to change directory (run as administrator?): { err . Message } ") ;
7073 }
7174
75+ const string repoURL = "https://github.com/roblox-csharp/roblox-cs.git" ;
76+ const string remoteName = "origin" ;
77+ var clonePath = Path . Combine ( path , "." ) ;
78+ var gitFolder = Path . Combine ( clonePath , ".git" ) ;
79+
80+ Repository ? repo = null ;
81+ if ( Directory . Exists ( gitFolder ) )
82+ {
83+ try
84+ {
85+ repo = new Repository ( gitFolder ) ;
86+ }
87+ catch ( Exception err )
88+ {
89+ ShowErrorMessageBox ( $ "Failed to create repository: { err . Message } \n { string . Join ( '\n ' , err . StackTrace ) } ") ;
90+ return ;
91+ }
92+ }
7293 StepProgress ( ) ;
94+
95+ Remote origin = null ! ;
96+ IEnumerable < string > refspecs = null ! ;
7397 Display ( "Pulling repository..." ) ;
7498 try
7599 {
76- var directoryEntries = Directory . GetFileSystemEntries ( "." ) ;
77- if ( directoryEntries . Length ! = 0 )
100+ var directoryEntries = Directory . GetFileSystemEntries ( clonePath ) ;
101+ if ( directoryEntries . Length = = 0 )
78102 {
79- ExecuteGitCommand ( "-v" , "Failed to run 'git' command (is git installed?)" ) ;
80- ExecuteGitCommand ( "pull origin master --allow-unrelated-histories" , "Failed to pull from the compiler repository" ) ;
103+ try
104+ {
105+ Repository . Clone ( repoURL , clonePath ) ;
106+ }
107+ catch ( Exception err )
108+ {
109+ ShowErrorMessageBox ( $ "Failed to clone the compiler repository: { err . Message } ") ;
110+ return ;
111+ }
81112 }
82- else
113+ if ( repo == null )
83114 {
84- ExecuteGitCommand ( "clone https://github.com/roblox-csharp/roblox-cs.git ." , "Failed to clone the compiler repository" ) ;
115+ try
116+ {
117+ repo = new Repository ( gitFolder ) ;
118+ }
119+ catch ( Exception err )
120+ {
121+ ShowErrorMessageBox ( $ "Failed to create repository: { err . Message } \n { string . Join ( '\n ' , err . StackTrace ) } ") ;
122+ return ;
123+ }
85124 }
125+ origin = repo . Network . Remotes [ remoteName ] ;
126+ refspecs = origin . FetchRefSpecs . Select ( refspec => refspec . ToString ( ) ) . OfType < string > ( ) ;
127+ GitPull ( repo , origin , refspecs ) ;
86128 }
87129 catch ( Exception err )
88130 {
89131 ShowErrorMessageBox ( $ "Failed to read the compiler repository directory (run as administrator?): { err . Message } ") ;
132+ return ;
90133 }
91134
92135 StepProgress ( ) ;
93136 Display ( "Fetching tags..." ) ;
94- ExecuteGitCommand ( "fetch --tags" , "Failed to fetch release tags" ) ;
137+ if ( repo == null ) return ;
138+ try
139+ {
140+ repo . Network . Fetch ( origin . Name , refspecs , new FetchOptions ( )
141+ {
142+ TagFetchMode = TagFetchMode . All
143+ } ) ;
144+ }
145+ catch ( Exception err )
146+ {
147+ ShowErrorMessageBox ( $ "Failed to fetch release tags from repository: { err . Message } ") ;
148+ }
95149 StepProgress ( ) ;
96150
97151 Display ( "Fetching latest release..." ) ;
98- _latestTag = ExecuteGitCommand ( "describe --tags --abbrev=0" , "Failed to get the latest release tag" ) ;
152+ var tags = repo . Tags ;
153+ _latestTag = tags . OrderByDescending ( tag => tag . FriendlyName ) . FirstOrDefault ( ) ! ;
154+ if ( _latestTag == null )
155+ {
156+ ShowErrorMessageBox ( $ "Failed to get the latest release tag, tags found: { repo . Tags . Count ( ) } ") ;
157+ return ;
158+ }
99159 StepProgress ( ) ;
100160
101161 Display ( "Checking out latest release..." ) ;
102- ExecuteGitCommand ( $ "checkout { _latestTag } ", "Failed to checkout the latest release" ) ;
162+ try
163+ {
164+ var commit = repo . Commits . FirstOrDefault ( commit => commit == ( Commit ) _latestTag . Target ) ;
165+ Commands . Checkout ( repo , commit ) ;
166+ }
167+ catch ( Exception err )
168+ {
169+ ShowErrorMessageBox ( $ "Failed to checkout the latest release: { err . Message } ") ;
170+ }
103171 StepProgress ( ) ;
104172
105173 Display ( "Building roblox-cs..." ) ;
@@ -143,7 +211,32 @@ public static void OnCredentialsAcquired(SourceCredentialsWindow credentialsWind
143211 Display ( "Successfully added roblox-cs to your PATH." ) ;
144212
145213 StepProgress ( ) ;
146- Display ( $ "Successfully installed roblox-cs ({ _latestTag } ).") ;
214+ Display ( $ "Successfully installed roblox-cs ({ _latestTag ? . FriendlyName ?? "???" } ).") ;
215+ }
216+
217+ private static void GitPull ( Repository repo , Remote remote , IEnumerable < string > refspecs )
218+ {
219+ try
220+ {
221+ repo . Network . Fetch ( remote . Name , refspecs ) ;
222+ }
223+ catch ( Exception err )
224+ {
225+ ShowErrorMessageBox ( $ "Failed to fetch origin/master from repository: { err . Message } ") ;
226+ }
227+ try
228+ {
229+ var branchToMerge = repo . Branches [ $ "{ remote . Name } /master"] ;
230+ var signature = new Signature ( "rbxcs-installer" , "[email protected] " , DateTimeOffset . Now ) ; 231+ var mergeResult = repo . Merge ( branchToMerge , signature , new MergeOptions
232+ {
233+ FileConflictStrategy = CheckoutFileConflictStrategy . Theirs
234+ } ) ;
235+ }
236+ catch ( Exception err )
237+ {
238+ ShowErrorMessageBox ( $ "Failed to merge: { err . Message } ") ;
239+ }
147240 }
148241
149242 private static void UpdateEnvironmentPath ( string path )
@@ -182,12 +275,6 @@ private static void UpdateShellProfilePath(string path)
182275 WriteProfile ( profilePath , pathUpdateCmd ) ;
183276 }
184277
185- private static string ExecuteGitCommand ( string arguments , string errorMessage )
186- {
187- var result = ExecuteCommand ( errorMessage , "git" , arguments . Split ( ' ' ) ) ;
188- return result . StandardOutput . Trim ( ) ;
189- }
190-
191278 private static ProcessResult ExecuteCommand ( string ? errorMessage , string command , params string [ ] arguments )
192279 {
193280 var startInfo = new ProcessStartInfo
0 commit comments