11using System ;
2- using System . Collections . Generic ;
32using System . IO ;
43using System . Net ;
5- using System . Threading ;
6- using System . Threading . Tasks ;
74using GitHub . Logging ;
8- using System . Linq ;
95
106namespace GitHub . Unity
117{
@@ -20,111 +16,39 @@ public DownloadData(UriString url, NPath file)
2016 }
2117 }
2218
23- class Downloader : FuncListTask < DownloadData >
19+ class Downloader : TaskQueue < NPath , DownloadData >
2420 {
25- public event Action < DownloadData > DownloadStart ;
26- public event Action < DownloadData > DownloadComplete ;
27- public event Action < DownloadData , Exception > DownloadFailed ;
21+ public event Action < UriString > OnDownloadStart ;
22+ public event Action < UriString , NPath > OnDownloadComplete ;
23+ public event Action < UriString , Exception > OnDownloadFailed ;
2824
29- private readonly List < DownloaderTask > downloaders = new List < DownloaderTask > ( ) ;
30-
31- public override string Message { get ; set ; } = "Downloading..." ;
32-
33- public Downloader ( ) : base ( TaskManager . Instance . Token , RunDownloaders )
25+ private readonly IFileSystem fileSystem ;
26+ public Downloader ( IFileSystem fileSystem )
27+ : base ( t =>
28+ {
29+ var dt = t as DownloadTask ;
30+ var destinationFile = dt . TargetDirectory . Combine ( dt . Url . Filename ) ;
31+ return new DownloadData ( dt . Url , destinationFile ) ;
32+ } )
3433 {
34+ this . fileSystem = fileSystem ;
3535 Name = "Downloader" ;
36+ Message = "Downloading..." ;
3637 }
3738
3839 public void QueueDownload ( UriString url , NPath targetDirectory )
3940 {
40- var downloaderTask = new DownloaderTask ( ) ;
41- downloaderTask . QueueDownload ( url , targetDirectory ) ;
42- downloaders . Add ( downloaderTask ) ;
43- }
44-
45- private static List < DownloadData > RunDownloaders ( bool success , FuncListTask < DownloadData > source )
46- {
47- Downloader self = ( Downloader ) source ;
48- List < DownloadData > result = null ;
49- var listOfTasks = new List < Task < DownloadData > > ( ) ;
50- foreach ( var downloader in self . downloaders )
51- {
52- downloader . DownloadStart += self . DownloadStart ;
53- downloader . DownloadComplete += self . DownloadComplete ;
54- downloader . DownloadFailed += self . DownloadFailed ;
55- listOfTasks . Add ( downloader . Run ( ) ) ;
56- }
57- var res = TaskEx . WhenAll ( listOfTasks ) . Result ;
58- if ( res != null )
59- result = new List < DownloadData > ( res ) ;
60- return result ;
61- }
62-
63- class DownloaderTask
64- {
65- public event Action < DownloadData > DownloadStart ;
66- public event Action < DownloadData > DownloadComplete ;
67- public event Action < DownloadData , Exception > DownloadFailed ;
68-
69- private readonly List < ITask < NPath > > queuedTasks = new List < ITask < NPath > > ( ) ;
70- private readonly TaskCompletionSource < DownloadData > aggregateDownloads = new TaskCompletionSource < DownloadData > ( ) ;
71- private readonly IFileSystem fs ;
72- private readonly CancellationToken cancellationToken ;
73-
74- private volatile bool isSuccessful = true ;
75- private volatile Exception exception ;
76- private DownloadData result ;
77-
78- public DownloaderTask ( )
79- {
80- fs = NPath . FileSystem ;
81- cancellationToken = TaskManager . Instance . Token ;
82- DownloadComplete += d => aggregateDownloads . TrySetResult ( d ) ;
83- DownloadFailed += ( _ , e ) => aggregateDownloads . TrySetException ( e ) ;
84- }
85-
86- public Task < DownloadData > Run ( )
87- {
88- foreach ( var task in queuedTasks )
89- task . Start ( ) ;
90- if ( queuedTasks . Count == 0 )
91- DownloadComplete ( result ) ;
92- return aggregateDownloads . Task ;
93- }
94-
95- public Task < DownloadData > QueueDownload ( UriString url , NPath targetDirectory )
41+ var download = new DownloadTask ( Token , fileSystem , url , targetDirectory ) ;
42+ download . OnStart += t => OnDownloadStart ? . Invoke ( ( ( DownloadTask ) t ) . Url ) ;
43+ download . OnEnd += ( t , res , s , ex ) =>
9644 {
97- var destinationFile = targetDirectory . Combine ( url . Filename ) ;
98- result = new DownloadData ( url , destinationFile ) ;
99-
100- Action < ITask < NPath > , NPath , bool , Exception > verifyDownload = ( t , res , success , ex ) =>
101- {
102- isSuccessful &= success ;
103- if ( ! success )
104- exception = ex ;
105- if ( ! isSuccessful )
106- {
107- DownloadFailed ( result , exception ) ;
108- }
109- else
110- {
111- DownloadComplete ( result ) ;
112- }
113- } ;
114-
115- var fileDownload = DownloadFile ( url , targetDirectory , result , verifyDownload ) ;
116- fileDownload . OnStart += _ => DownloadStart ? . Invoke ( result ) ;
117- queuedTasks . Add ( fileDownload ) ;
118- return aggregateDownloads . Task ;
119- }
120-
121- private ITask < NPath > DownloadFile ( UriString url , NPath targetDirectory , DownloadData res , Action < ITask < NPath > , NPath , bool , Exception > verifyDownload )
122- {
123- var download = new DownloadTask ( cancellationToken , fs , url , targetDirectory )
124- . Catch ( e => { DownloadFailed ( res , e ) ; return true ; } ) ;
125- download . OnEnd += verifyDownload ;
126- return download ;
127- }
45+ if ( s )
46+ OnDownloadComplete ? . Invoke ( ( ( DownloadTask ) t ) . Url , res ) ;
47+ else
48+ OnDownloadFailed ? . Invoke ( ( ( DownloadTask ) t ) . Url , ex ) ;
49+ } ;
50+ // queue after hooking up events so OnDownload* gets called first
51+ Queue ( download ) ;
12852 }
12953
13054 public static bool Download ( ILogging logger , UriString url ,
0 commit comments