Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
M
mycard
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
syntax_j
mycard
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