Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
M
moecube
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Locked Files
Issues
0
Issues
0
List
Boards
Labels
Service Desk
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Security & Compliance
Security & Compliance
Dependency List
License Compliance
Packages
Packages
List
Container Registry
Analytics
Analytics
CI / CD
Code Review
Insights
Issues
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
JoyJ
moecube
Commits
10141262
Commit
10141262
authored
Dec 09, 2016
by
神楽坂玲奈
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'v3' of github.com:mycard/mycard into v3
parents
2e4df7f6
97fd7c71
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
173 additions
and
140 deletions
+173
-140
app/app-detail.component.html
app/app-detail.component.html
+1
-1
app/app-detail.component.ts
app/app-detail.component.ts
+12
-2
app/apps.service.ts
app/apps.service.ts
+126
-112
app/download.service.ts
app/download.service.ts
+34
-25
No files found.
app/app-detail.component.html
View file @
10141262
...
...
@@ -66,7 +66,7 @@
<td
*ngIf=
"!mod.isInstalled()"
>
<button
i18n
(click)=
"installMod(mod)"
type=
"button"
*ngIf=
"!mod.isInstalled()"
class=
"btn btn-primary btn-sm"
>
安装
</button>
</td>
<td
*ngIf=
"mod.isInstalled()&&!mod.isReady()"
>
:
<td
*ngIf=
"mod.isInstalled()&&!mod.isReady()"
>
<progress
class=
"progress progress-striped progress-animated"
value=
"{{mod.status.progress}}"
max=
"{{mod.status.total}}"
></progress>
<!--<div i18n *ngIf="mod.isWaiting()">等待安装...</div>-->
</td>
...
...
app/app-detail.component.ts
View file @
10141262
...
...
@@ -145,8 +145,18 @@ export class AppDetailComponent implements OnInit {
this
.
appsService
.
runApp
(
app
,
'
custom
'
);
}
verifyFiles
(
app
:
App
)
{
this
.
appsService
.
verifyFiles
(
app
);
async
verifyFiles
(
app
:
App
)
{
try
{
await
this
.
appsService
.
update
(
app
,
true
);
let
installedMods
=
this
.
appsService
.
findChildren
(
app
).
filter
((
child
)
=>
{
return
child
.
parent
===
app
&&
child
.
isInstalled
()
&&
child
.
isReady
();
});
for
(
let
mod
of
installedMods
)
{
await
this
.
appsService
.
update
(
mod
,
true
);
}
}
catch
(
e
)
{
console
.
log
(
e
);
}
}
copy
(
text
:
string
)
{
...
...
app/apps.service.ts
View file @
10141262
...
...
@@ -267,39 +267,29 @@ export class AppsService {
});
}
async
verifyFiles
(
app
:
App
)
{
if
(
app
.
isReady
())
{
app
.
status
.
status
=
"
updating
"
;
Logger
.
info
(
"
Start to verify files:
"
,
app
);
let
lastedFile
=
await
this
.
getChecksumFile
(
app
);
let
changedList
:
string
[]
=
[];
for
(
let
[
file
,
checksum
]
of
lastedFile
)
{
let
absolutePath
=
path
.
join
(
app
.
local
!
.
path
,
file
);
await
new
Promise
((
resolve
,
reject
)
=>
{
fs
.
access
(
absolutePath
,
fs
.
constants
.
F_OK
,
(
err
)
=>
{
if
(
err
)
{
changedList
.
push
(
file
);
}
resolve
();
});
});
if
(
checksum
!==
""
)
{
let
c
=
await
this
.
sha256sum
(
file
);
if
(
c
!==
checksum
)
{
changedList
.
push
(
file
);
async
verifyFiles
(
app
:
App
,
checksumFiles
:
Map
<
string
,
string
>
):
Promise
<
Map
<
string
,
string
>>
{
let
result
=
new
Map
<
string
,
string
>
();
for
(
let
[
file
,
checksum
]
of
checksumFiles
)
{
let
filePath
=
path
.
join
(
app
.
local
!
.
path
,
file
);
// 如果文件不存在,随便生成一个checksum
await
new
Promise
((
resolve
,
reject
)
=>
{
fs
.
access
(
filePath
,
fs
.
constants
.
F_OK
,
async
(
err
:
Error
)
=>
{
if
(
err
)
{
result
.
set
(
file
,
Math
.
random
().
toString
());
}
else
if
(
checksum
===
""
)
{
result
.
set
(
file
,
""
);
}
else
{
let
sha256sum
=
await
this
.
sha256sum
(
filePath
);
result
.
set
(
file
,
sha256sum
);
}
}
}
await
this
.
doUpdate
(
app
,
changedList
);
app
.
status
.
status
=
"
ready
"
;
resolve
();
});
});
}
return
result
;
}
async
update
(
app
:
App
)
{
async
update
(
app
:
App
,
verify
=
false
)
{
let
readyToUpdate
:
boolean
=
false
;
// 已经安装的mod
let
mods
=
this
.
findChildren
(
app
).
filter
((
mod
)
=>
{
...
...
@@ -307,91 +297,112 @@ export class AppsService {
});
// 如果是不是mod,那么要所有已经安装mod都ready
// 如果是mod,那么要parent ready
if
(
app
.
parent
&&
app
.
parent
.
isReady
())
{
if
(
app
.
parent
&&
app
.
parent
.
isReady
()
&&
app
.
isReady
()
)
{
readyToUpdate
=
true
;
}
else
{
readyToUpdate
=
mods
.
every
((
mod
)
=>
{
return
mod
.
isReady
();
})
readyToUpdate
=
app
.
isReady
()
&&
mods
.
every
((
mod
)
=>
mod
.
isReady
());
}
if
(
readyToUpdate
&&
app
.
local
!
.
version
!==
app
.
version
)
{
if
(
readyToUpdate
&&
(
app
.
local
!
.
version
!==
app
.
version
||
verify
)
)
{
app
.
status
.
status
=
"
updating
"
;
Logger
.
info
(
"
Checking updating:
"
,
app
);
let
latestFiles
=
await
this
.
getChecksumFile
(
app
);
let
localFiles
=
app
.
local
!
.
files
;
let
changedFiles
:
Set
<
string
>
=
new
Set
<
string
>
()
;
let
deletedFiles
:
Set
<
string
>
=
new
Set
<
string
>
();
for
(
let
[
file
,
checksum
]
of
latestFiles
)
{
if
(
!
localFiles
.
has
(
file
))
{
changedFiles
.
add
(
file
)
;
try
{
Logger
.
info
(
"
Checking updating:
"
,
app
);
let
latestFiles
=
await
this
.
getChecksumFile
(
app
)
;
let
localFiles
:
Map
<
string
,
string
>
;
if
(
verify
)
{
localFiles
=
await
this
.
verifyFiles
(
app
,
latestFiles
);
}
else
{
localFiles
=
app
.
local
!
.
files
;
}
}
for
(
let
[
file
,
checksum
]
of
localFiles
)
{
if
(
latestFiles
.
has
(
file
))
{
if
(
latestFiles
.
get
(
file
)
!==
checksum
)
{
let
addedFiles
:
Set
<
string
>
=
new
Set
<
string
>
();
let
changedFiles
:
Set
<
string
>
=
new
Set
<
string
>
();
let
deletedFiles
:
Set
<
string
>
=
new
Set
<
string
>
();
// 遍历寻找新增加的文件
for
(
let
[
file
,
checksum
]
of
latestFiles
)
{
if
(
!
localFiles
.
has
(
file
))
{
changedFiles
.
add
(
file
);
addedFiles
.
add
(
file
);
}
}
else
{
deletedFiles
.
add
(
file
);
}
}
let
backupFiles
:
string
[]
=
[];
let
restoreFiles
:
string
[]
=
[];
if
(
app
.
parent
)
{
let
parentFiles
=
app
.
parent
.
local
!
.
files
;
// 添加的文件和parent冲突,且不是目录,就添加到conflict列表
for
(
let
changedFile
of
changedFiles
)
{
if
(
parentFiles
.
has
(
changedFile
)
&&
parentFiles
.
get
(
changedFile
)
!==
""
)
{
backupFiles
.
push
(
changedFile
);
// 遍历寻找旧版本与新版本不一样的文件和新版本比旧版少了的文件
for
(
let
[
file
,
checksum
]
of
localFiles
)
{
if
(
latestFiles
.
has
(
file
))
{
if
(
latestFiles
.
get
(
file
)
!==
checksum
)
{
changedFiles
.
add
(
file
);
}
}
else
{
deletedFiles
.
add
(
file
);
}
}
//如果要删除的文件parent里也有就恢复这个文件
for
(
let
deletedFile
of
deletedFiles
)
{
restoreFiles
.
push
(
deletedFile
);
}
let
backupDir
=
path
.
join
(
path
.
dirname
(
app
.
local
!
.
path
),
"
backup
"
,
app
.
parent
.
id
);
await
this
.
backupFiles
(
app
.
local
!
.
path
,
backupDir
,
backupFiles
);
await
this
.
restoreFiles
(
app
.
local
!
.
path
,
backupDir
,
restoreFiles
);
}
else
{
for
(
let
mod
of
mods
)
{
// 如果changed列表与已经安装的mod有冲突,就push到back列表里
for
(
let
changedFile
of
changedFiles
)
{
if
(
mod
.
local
!
.
files
.
has
(
changedFile
))
{
backupFiles
.
push
(
changedFile
);
let
backupFiles
:
string
[]
=
[];
let
restoreFiles
:
string
[]
=
[];
if
(
app
.
parent
)
{
let
parentFiles
=
app
.
parent
.
local
!
.
files
;
// 新增加的文件和parent冲突,且不是目录,就添加backup到
// 改变的文件不做备份
for
(
let
addedFile
of
addedFiles
)
{
if
(
parentFiles
.
has
(
addedFile
)
&&
parentFiles
.
get
(
addedFile
)
!==
""
)
{
backupFiles
.
push
(
addedFile
);
}
}
//
如果要删除的文件,mod里面存在,就不要删除
这个文件
//
如果要删除的文件parent里也有就恢复
这个文件
for
(
let
deletedFile
of
deletedFiles
)
{
if
(
mod
.
local
!
.
files
.
has
(
deletedFile
))
{
deletedFiles
.
delete
(
deletedFile
);
}
restoreFiles
.
push
(
deletedFile
);
}
let
backupDir
=
path
.
join
(
path
.
dirname
(
app
.
local
!
.
path
),
"
mods_backup
"
,
app
.
id
);
}
}
// 筛选更新文件中与mod冲突的部分
for
(
let
mod
of
installedMods
)
{
changedFiles
.
forEach
((
changedFile
)
=>
{
if
(
mod
.
local
!
.
files
.
has
(
changedFile
))
{
conflictFiles
.
add
(
changedFile
);
}
});
deletedFiles
.
forEach
((
deletedFile
)
=>
{
if
(
mod
.
local
!
.
files
.
has
(
deletedFile
))
{
deletedFiles
.
delete
(
deletedFile
);
let
backupDir
=
path
.
join
(
path
.
dirname
(
app
.
local
!
.
path
),
"
backup
"
,
app
.
parent
.
id
);
await
this
.
backupFiles
(
app
.
local
!
.
path
,
backupDir
,
backupFiles
);
await
this
.
restoreFiles
(
app
.
local
!
.
path
,
backupDir
,
restoreFiles
);
}
else
{
for
(
let
mod
of
mods
)
{
// 更新时,冲突文件在backup目录里,需要更新backup目录里的文件
// 如果changed列表与已经安装的mod有冲突,就push到backup列表里
// 然后先把当前的mod文件被分到mods_backup目录再解压更新,把文件备份到backup,最后从mods_backup里恢复mods文件
// 校验时,认为mod的文件正确,把冲突文件从changed列表里面删除掉
for
(
let
changedFile
of
changedFiles
)
{
if
(
mod
.
local
!
.
files
.
has
(
changedFile
))
{
if
(
!
verify
)
{
backupFiles
.
push
(
changedFile
);
}
else
{
changedFiles
.
delete
(
changedFile
);
}
}
}
let
backupToDelete
:
string
[]
=
[];
// 如果要删除的文件,mod里面存在,就删除backup目录里的文件
for
(
let
deletedFile
of
deletedFiles
)
{
if
(
mod
.
local
!
.
files
.
has
(
deletedFile
))
{
backupToDelete
.
push
(
deletedFile
);
}
}
let
backupDir
=
path
.
join
(
path
.
dirname
(
app
.
local
!
.
path
),
"
mods_backup
"
,
app
.
id
);
await
this
.
backupFiles
(
app
.
local
!
.
path
,
backupDir
,
backupFiles
);
for
(
let
file
of
backupToDelete
)
{
await
this
.
deleteFile
(
path
.
join
(
app
.
local
!
.
path
,
file
))
}
}
})
}
await
this
.
doUpdate
(
app
,
changedFiles
,
deletedFiles
);
Logger
.
info
(
"
Update extract finished
"
);
//如果不是mod,就先把自己目录里最新的冲突文件backup到backup目录
//再把mods_backup里面的文件恢复到游戏目录
if
(
!
app
.
parent
)
{
Logger
.
info
(
"
Start to restore files...
"
);
let
modsBackupDir
=
path
.
join
(
path
.
dirname
(
app
.
local
!
.
path
),
"
mods_backup
"
,
app
.
id
);
let
appBackupDir
=
path
.
join
(
path
.
dirname
(
app
.
local
!
.
path
),
"
backup
"
,
app
.
id
);
await
this
.
backupFiles
(
app
.
local
!
.
path
,
appBackupDir
,
backupFiles
);
await
this
.
restoreFiles
(
app
.
local
!
.
path
,
modsBackupDir
,
backupFiles
);
}
app
.
local
!
.
version
=
app
.
version
;
app
.
local
!
.
files
=
latestFiles
;
this
.
saveAppLocal
(
app
);
app
.
status
.
status
=
"
ready
"
;
Logger
.
info
(
"
Update Finished:
"
,
app
);
}
catch
(
e
)
{
Logger
.
error
(
"
Update Failed:
"
,
e
);
app
.
status
.
status
=
"
ready
"
;
}
await
this
.
doUpdate
(
app
,
changedFiles
,
deletedFiles
);
app
.
local
!
.
version
=
app
.
version
;
app
.
local
!
.
files
=
latestFiles
;
this
.
saveAppLocal
(
app
);
app
.
status
.
status
=
"
ready
"
;
installedMods
.
forEach
((
mod
)
=>
mod
.
status
.
status
=
"
ready
"
);
Logger
.
info
(
"
Update Finished:
"
,
app
);
}
}
...
...
@@ -405,15 +416,13 @@ export class AppsService {
}
let
metalink
=
await
this
.
http
.
post
(
updateUrl
,
changedFiles
).
map
((
response
)
=>
response
.
text
()).
toPromise
();
let
downloadDir
=
path
.
join
(
path
.
dirname
(
app
.
local
!
.
path
),
"
downloading
"
);
let
downloadId
=
await
this
.
downloadService
.
addMetalink
(
metalink
,
downloadDir
);
await
this
.
downloadService
.
progress
(
downloadId
,
(
status
:
DownloadStatus
)
=>
{
app
.
status
.
progress
=
status
.
completedLength
;
app
.
status
.
total
=
status
.
totalLength
;
app
.
status
.
progressMessage
=
status
.
downloadSpeedText
;
this
.
ref
.
tick
();
});
let
downloadId
=
await
this
.
downloadService
.
addMetalink
(
metalink
,
downloadDir
);
await
this
.
downloadService
.
progress
(
downloadId
,
(
status
:
DownloadStatus
)
=>
{
app
.
status
.
progress
=
status
.
completedLength
;
app
.
status
.
total
=
status
.
totalLength
;
app
.
status
.
progressMessage
=
status
.
downloadSpeedText
;
this
.
ref
.
tick
();
});
let
downloadFiles
=
await
this
.
downloadService
.
getFiles
(
downloadId
);
for
(
let
downloadFile
of
downloadFiles
)
{
await
new
Promise
((
resolve
,
reject
)
=>
{
...
...
@@ -433,6 +442,7 @@ export class AppsService {
await
this
.
deleteFile
(
path
.
join
(
app
.
local
!
.
path
,
deletedFile
));
}
}
}
async
install
(
app
:
App
,
option
:
InstallOption
)
{
...
...
@@ -462,12 +472,16 @@ export class AppsService {
app
.
status
.
status
=
"
downloading
"
;
let
metalink
=
await
this
.
http
.
get
(
metalinkUrl
).
map
((
response
)
=>
response
.
text
()).
toPromise
();
let
downloadId
=
await
this
.
downloadService
.
addMetalink
(
metalink
,
dir
);
await
this
.
downloadService
.
progress
(
downloadId
,
(
status
:
DownloadStatus
)
=>
{
app
.
status
.
progress
=
status
.
completedLength
;
app
.
status
.
total
=
status
.
totalLength
;
app
.
status
.
progressMessage
=
status
.
downloadSpeedText
;
this
.
ref
.
tick
();
});
try
{
await
this
.
downloadService
.
progress
(
downloadId
,
(
status
:
DownloadStatus
)
=>
{
app
.
status
.
progress
=
status
.
completedLength
;
app
.
status
.
total
=
status
.
totalLength
;
app
.
status
.
progressMessage
=
status
.
downloadSpeedText
;
this
.
ref
.
tick
();
});
}
catch
(
e
)
{
}
let
files
=
await
this
.
downloadService
.
getFiles
(
downloadId
);
app
.
status
.
status
=
"
waiting
"
;
return
{
app
:
app
,
files
:
files
}
...
...
app/download.service.ts
View file @
10141262
...
...
@@ -112,6 +112,7 @@ export class DownloadService {
let
activeList
=
await
this
.
aria2
.
tellActive
();
let
waitList
=
await
this
.
aria2
.
tellWaiting
(
0
,
MAX_LIST_NUM
);
let
stoppedList
=
await
this
.
aria2
.
tellStopped
(
0
,
MAX_LIST_NUM
);
this
.
downloadList
.
clear
();
for
(
let
item
of
activeList
)
{
this
.
downloadList
.
set
(
item
.
gid
,
new
DownloadStatus
(
item
));
}
...
...
@@ -142,33 +143,41 @@ export class DownloadService {
let
gids
=
this
.
taskMap
.
get
(
id
);
if
(
gids
)
{
let
allStatus
:
DownloadStatus
;
this
.
updateEmitter
.
subscribe
(()
=>
{
let
status
:
DownloadStatus
=
new
DownloadStatus
();
// 合并每个状态信息
status
=
gids
!
.
map
((
value
,
index
,
array
)
=>
{
let
s
=
this
.
downloadList
.
get
(
value
);
if
(
!
s
)
{
throw
new
Error
(
"
Gid not Exists
"
);
}
return
s
;
})
.
reduce
((
previousValue
,
currentValue
,
currentIndex
,
array
)
=>
{
return
previousValue
.
combine
(
currentValue
);
},
status
);
if
(
!
allStatus
)
{
allStatus
=
status
;
}
else
{
if
(
allStatus
.
compareTo
(
status
)
!=
0
)
{
let
subscription
=
this
.
updateEmitter
.
subscribe
(()
=>
{
try
{
let
status
:
DownloadStatus
=
new
DownloadStatus
();
// 合并每个状态信息
status
=
gids
!
.
map
((
value
,
index
,
array
)
=>
{
let
s
=
this
.
downloadList
.
get
(
value
);
if
(
!
s
)
{
throw
"
Gid not exists
"
;
}
return
s
;
})
.
reduce
((
previousValue
,
currentValue
,
currentIndex
,
array
)
=>
{
return
previousValue
.
combine
(
currentValue
);
},
status
);
if
(
!
allStatus
)
{
allStatus
=
status
;
}
else
{
if
(
allStatus
.
compareTo
(
status
)
!=
0
)
{
allStatus
=
status
;
}
}
}
if
(
allStatus
.
status
===
"
error
"
)
{
reject
(
`Download Error: code
${
allStatus
.
errorCode
}
, message:
${
allStatus
.
errorMessage
}
`
);
}
else
if
(
allStatus
.
status
===
"
complete
"
)
{
resolve
();
}
else
{
callback
(
allStatus
);
if
(
allStatus
.
status
===
"
error
"
)
{
throw
`Download Error: code
${
allStatus
.
errorCode
}
, message:
${
allStatus
.
errorMessage
}
`
;
}
else
if
(
allStatus
.
status
===
"
complete
"
)
{
resolve
();
subscription
.
unsubscribe
();
}
else
{
callback
(
allStatus
);
}
}
catch
(
e
)
{
reject
(
e
);
subscription
.
unsubscribe
();
}
});
}
else
{
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment