Skip to content
Projeler
Gruplar
Parçacıklar
Yardım
Yükleniyor...
Oturum aç / Kaydol
Gezinmeyi değiştir
I
inary
Proje
Proje
Ayrıntılar
Etkinlik
Cycle Analytics
Depo (repository)
Depo (repository)
Dosyalar
Kayıtlar (commit)
Dallar (branch)
Etiketler
Katkıda bulunanlar
Grafik
Karşılaştır
Grafikler
Konular (issue)
1
Konular (issue)
1
Liste
Pano
Etiketler
Kilometre Taşları
Birleştirme (merge) Talepleri
0
Birleştirme (merge) Talepleri
0
CI / CD
CI / CD
İş akışları (pipeline)
İşler
Zamanlamalar
Grafikler
Paketler
Paketler
Wiki
Wiki
Parçacıklar
Parçacıklar
Üyeler
Üyeler
Collapse sidebar
Close sidebar
Etkinlik
Grafik
Grafikler
Yeni bir konu (issue) oluştur
İşler
Kayıtlar (commit)
Konu (issue) Panoları
Kenar çubuğunu aç
SulinOS
inary
Commits
5c880a51
Kaydet (Commit)
5c880a51
authored
May 21, 2020
tarafından
Ali Rıza KESKİN
Dosyalara gözat
Seçenekler
Dosyalara Gözat
İndir
Eposta Yamaları
Sade Fark
pep8 kuralları düzeltmesi
üst
178095d7
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
23 changed files
with
250 additions
and
184 deletions
+250
-184
AUTHORS
AUTHORS
+7
-7
COPYING.PISI_FORK
COPYING.PISI_FORK
+1
-1
FIXME.md
FIXME.md
+7
-7
PKG-INFO
PKG-INFO
+4
-4
__init__.py
inary/__init__.py
+4
-2
api.py
inary/api.py
+48
-50
archive.py
inary/archive.py
+0
-0
atomicoperations.py
inary/atomicoperations.py
+0
-0
blacklist.py
inary/blacklist.py
+2
-1
config.py
inary/config.py
+13
-11
configfile.py
inary/configfile.py
+7
-5
constants.py
inary/constants.py
+6
-4
itembyrepo.py
inary/db/itembyrepo.py
+1
-1
fetcher.py
inary/fetcher.py
+0
-0
file.py
inary/file.py
+59
-29
mirrors.py
inary/mirrors.py
+4
-1
package.py
inary/package.py
+28
-21
process.py
inary/process.py
+2
-2
sysconf.py
inary/sysconf.py
+25
-18
trigger.py
inary/trigger.py
+21
-13
ui.py
inary/ui.py
+1
-1
util.py
inary/util.py
+0
-0
version.py
inary/version.py
+10
-6
No files found.
AUTHORS
Dosyayı görüntüle @
5c880a51
Old_Author
-----------
Tubitak
-UEKAE <uekae [at] tubitak.org,tr
>
Tubitak
- UEKAE < uekae[at] tubitak.org, tr
>
Updates and Developings
...
...
@@ -8,22 +8,22 @@ since 2016
Maintainers
-----------
Suleyman POYRAZ <
nipalensisaquila [at] gmail.com
>
Suleyman POYRAZ <
nipalensisaquila[at] gmail.com
>
Developers
----------
Suleyman POYRAZ <
nipalensisaquila [at] gmail.com
>
parduscix
(Ali Rıza Keskin) <parduscix [at] pardustopluluk.org
>
Suleyman POYRAZ <
nipalensisaquila[at] gmail.com
>
parduscix
(Ali Rıza Keskin) < parduscix[at] pardustopluluk.org
>
Contributors
------------
Suleyman POYRAZ <
nipalensisaquila [at] gmail.com
>
parduscix
(Ali Rıza Keskin) <parduscix [at] pardustopluluk.org
>
Suleyman POYRAZ <
nipalensisaquila[at] gmail.com
>
parduscix
(Ali Rıza Keskin) < parduscix[at] pardustopluluk.org
>
Fuat BOLUK
Thanks for:
-----------
Ilker MANAP: repodb.py, lambda function problem
Fuat BOLUK: type error(str
-
unicode type problem)
Fuat BOLUK: type error(str
-
unicode type problem)
COPYING.PISI_FORK
Dosyayı görüntüle @
5c880a51
NOTE! The GPL below is copyrighted by the Free Software Foundation, but
the instance of code that it refers to
(the kde programs) are copyrighted
the instance of code that it refers to(the kde programs) are copyrighted
by the authors who actually wrote it.
---------------------------------------------------------------------------
...
...
FIXME.md
Dosyayı görüntüle @
5c880a51
2019
-01-08 Suleyman POYRAZ
<zaryob.dev@gmail.com
>
*
dependency error -
-status: not fixed; flag: critical -
--:
2019
- 01 - 08 Suleyman POYRAZ
< zaryob.dev @ gmail.com
>
*
dependency error -
-status: not fixed; flag: critical -
--:
-> çalışma sırasında dependencylere göre paketler kurulum sıralamasına sokulmadığı içinde
error veriyor sonuç olarak kurulumun ortasında hata yiyoruz. Önceden beri var olan bu hata giderilmeli.
2018
-05-05 Suleyman POYRAZ
<zaryob.dev@gmail.com
>
*
inary.data.pgraph.py -
-status: fixed; flag: critical -
--:
2018
- 05 - 05 Suleyman POYRAZ
< zaryob.dev @ gmail.com
>
*
inary.data.pgraph.py -
-status: fixed; flag: critical -
--:
->inary kurulum için mevcut dizin olarak farklı bir yer kulllanılınca pgraph.Digraph()
sınıfındaki dfs fonksiyonlarından KeyError yükseliyor.
2018
-03-17 Suleyman POYRAZ
<zaryob.dev@gmail.com
>
*
inary.fetcher.py: --- status: fixed; flag: critical ---:
2018
- 03 - 17 Suleyman POYRAZ
< zaryob.dev @ gmail.com
>
*
inary.fetcher.py: --- status: fixed; flag: critical -
--:
->Ufak bir sihirli dokunuş düzeltmeye yetti.
Neden local dosyaları çekmiyor bu?
"""
...
...
PKG-INFO
Dosyayı görüntüle @
5c880a51
Metadata
-
Version: 1.0
Metadata
-
Version: 1.0
Name: inary
Version: 1.0
Summary: Inary
(Special Package Manager)
Home
-page: https://gitlab.com/sulinos/sulinproject/
inary
Summary: Inary(Special Package Manager)
Home
- page: https: // gitlab.com / sulinos / sulinproject /
inary
Author: Sulin Project Developers
Author
-email: zaryob.dev@
gmail.com
Author
- email: zaryob.dev @
gmail.com
License: GNU GPL3
Description: Inary is the package management system of Sulin Linux and use with Mac OS, Solaris and FreeBSD
Platform: UNKNOWN
inary/__init__.py
Dosyayı görüntüle @
5c880a51
...
...
@@ -33,8 +33,10 @@ import inary.context as ctx
def
init_logging
():
log_dir
=
os
.
path
.
join
(
ctx
.
config
.
dest_dir
(),
ctx
.
config
.
log_dir
())
if
os
.
access
(
log_dir
,
os
.
W_OK
)
and
"distutils.core"
not
in
sys
.
modules
:
handler
=
logging
.
handlers
.
RotatingFileHandler
(
'{}/inary.log'
.
format
(
log_dir
))
formatter
=
logging
.
Formatter
(
'
%(asctime)-12
s:
%(name)
s(
%(module)
s:
%(lineno)4
d)
%(levelname)
s
%(message)
s'
)
handler
=
logging
.
handlers
.
RotatingFileHandler
(
'{}/inary.log'
.
format
(
log_dir
))
formatter
=
logging
.
Formatter
(
'
%(asctime)-12
s:
%(name)
s(
%(module)
s:
%(lineno)4
d)
%(levelname)
s
%(message)
s'
)
handler
.
setFormatter
(
formatter
)
ctx
.
log
=
logging
.
getLogger
(
'inary'
)
ctx
.
log
.
addHandler
(
handler
)
...
...
inary/api.py
Dosyayı görüntüle @
5c880a51
...
...
@@ -12,6 +12,54 @@
# Please read the COPYING file.
from
inary.operations.search
import
*
from
inary.operations.upgrade
import
upgrade
,
get_upgrade_order
,
get_base_upgrade_order
from
inary.operations.repository
import
*
from
inary.operations.remove
import
remove
,
get_remove_order
from
inary.operations.install
import
install
,
get_install_order
from
inary.operations.info
import
info
from
inary.operations.history
import
takeback
,
get_takeback_plan
,
snapshot
from
inary.operations.helper
import
calculate_download_sizes
,
calculate_free_space_needed
,
get_package_requirements
from
inary.operations.emerge
import
emerge
from
inary.operations.check
import
check
from
inary.operations.build
import
build
,
build_until
from
inary.fetcher
import
fetch
from
inary.data.pgraph
import
package_graph
from
inary.data.index
import
index
from
inary.db.filesdb
import
rebuild_db
from
inary.analyzer.conflict
import
calculate_conflicts
import
inary.util
import
inary.uri
import
inary.operations.upgrade
import
inary.operations.search
import
inary.operations.repository
import
inary.operations.remove
import
inary.operations.helper
import
inary.operations.history
import
inary.operations.install
import
inary.operations.info
import
inary.operations.emerge
import
inary.operations.check
import
inary.operations.build
import
inary.file
import
inary.errors
import
inary.db.groupdb
import
inary.db.sourcedb
import
inary.db.historydb
import
inary.db.installdb
import
inary.db.filesdb
import
inary.db.repodb
import
inary.db.packagedb
import
inary.db.componentdb
import
inary.data.pgraph
import
inary.data.metadata
import
inary.data.index
import
inary.data
import
inary.context
as
ctx
import
inary.config
import
inary.blacklist
import
inary.atomicoperations
import
inary
from
.
import
fetcher
# Gettext Library
...
...
@@ -19,48 +67,14 @@ import gettext
__trans
=
gettext
.
translation
(
'inary'
,
fallback
=
True
)
_
=
__trans
.
gettext
import
inary
import
inary.atomicoperations
import
inary.blacklist
import
inary.config
import
inary.context
as
ctx
# DataFile Libraries
import
inary.data
import
inary.data.index
import
inary.data.metadata
import
inary.data.pgraph
# DataBase Libraries
import
inary.db.componentdb
import
inary.db.packagedb
import
inary.db.repodb
import
inary.db.filesdb
import
inary.db.installdb
import
inary.db.historydb
import
inary.db.sourcedb
import
inary.db.componentdb
import
inary.db.groupdb
import
inary.errors
import
inary.file
# Operation Libraries
import
inary.operations.build
import
inary.operations.check
import
inary.operations.emerge
import
inary.operations.info
import
inary.operations.install
import
inary.operations.history
import
inary.operations.helper
import
inary.operations.remove
import
inary.operations.repository
import
inary.operations.search
import
inary.operations.upgrade
import
inary.uri
import
inary.util
def
set_userinterface
(
ui
):
"""
...
...
@@ -133,19 +147,3 @@ def set_options(options):
# The following are INARY operations which constitute the INARY API
# Within functions
from
inary.analyzer.conflict
import
calculate_conflicts
from
inary.db.filesdb
import
rebuild_db
from
inary.data.index
import
index
from
inary.data.pgraph
import
package_graph
from
inary.fetcher
import
fetch
from
inary.operations.build
import
build
,
build_until
from
inary.operations.check
import
check
from
inary.operations.emerge
import
emerge
from
inary.operations.helper
import
calculate_download_sizes
,
calculate_free_space_needed
,
get_package_requirements
from
inary.operations.history
import
takeback
,
get_takeback_plan
,
snapshot
from
inary.operations.info
import
info
from
inary.operations.install
import
install
,
get_install_order
from
inary.operations.remove
import
remove
,
get_remove_order
from
inary.operations.repository
import
*
from
inary.operations.upgrade
import
upgrade
,
get_upgrade_order
,
get_base_upgrade_order
from
inary.operations.search
import
*
inary/archive.py
Dosyayı görüntüle @
5c880a51
This diff is collapsed.
Click to expand it.
inary/atomicoperations.py
Dosyayı görüntüle @
5c880a51
This diff is collapsed.
Click to expand it.
inary/blacklist.py
Dosyayı görüntüle @
5c880a51
...
...
@@ -44,7 +44,8 @@ def exclude(packages, patterns):
if
not
match
:
# match pattern in component names
for
compare
in
fnmatch
.
filter
(
componentdb
.
list_components
(),
pattern
):
for
compare
in
fnmatch
.
filter
(
componentdb
.
list_components
(),
pattern
):
packages
-=
set
(
componentdb
.
get_union_packages
(
compare
,
walk
=
True
))
return
list
(
packages
)
inary/config.py
Dosyayı görüntüle @
5c880a51
...
...
@@ -17,6 +17,10 @@ INARY Configuration module is used for gathering and providing
regular INARY configurations.
"""
import
inary.util
as
util
import
inary.errors
import
inary.configfile
import
inary.context
as
ctx
import
copy
import
os
from
pathlib
import
Path
...
...
@@ -26,11 +30,6 @@ import gettext
__trans
=
gettext
.
translation
(
'inary'
,
fallback
=
True
)
_
=
__trans
.
gettext
import
inary.context
as
ctx
import
inary.configfile
import
inary.errors
import
inary.util
as
util
class
Error
(
inary
.
errors
.
Error
):
pass
...
...
@@ -54,13 +53,14 @@ class Config(object, metaclass=util.Singleton):
self
.
set_options
(
options
)
if
Path
(
"/etc/inary/inary.conf"
)
.
is_file
():
self
.
values
=
inary
.
configfile
.
ConfigurationFile
(
"/etc/inary/inary.conf"
)
self
.
values
=
inary
.
configfile
.
ConfigurationFile
(
"/etc/inary/inary.conf"
)
elif
Path
(
"inary.conf"
)
.
is_file
():
self
.
values
=
inary
.
configfile
.
ConfigurationFile
(
"inary.conf"
)
self
.
values
=
inary
.
configfile
.
ConfigurationFile
(
"inary.conf"
)
else
:
# config not found but class needed
self
.
values
=
inary
.
configfile
.
ConfigurationFile
(
""
)
# config not found but class needed
self
.
values
=
inary
.
configfile
.
ConfigurationFile
(
""
)
# get the initial environment variables. this is needed for
# build process.
self
.
environ
=
copy
.
deepcopy
(
os
.
environ
)
...
...
@@ -94,7 +94,9 @@ class Config(object, metaclass=util.Singleton):
self
.
__dest_dir
=
self
.
values
.
general
.
destinationdirectory
if
not
os
.
path
.
exists
(
self
.
__dest_dir
):
ctx
.
ui
.
warning
(
_
(
"Destination directory
\"
{}
\"
does not exist. Creating it."
)
.
format
(
self
.
__dest_dir
))
ctx
.
ui
.
warning
(
_
(
"Destination directory
\"
{}
\"
does not exist. Creating it."
)
.
format
(
self
.
__dest_dir
))
os
.
makedirs
(
self
.
__dest_dir
)
return
self
.
__dest_dir
...
...
inary/configfile.py
Dosyayı görüntüle @
5c880a51
...
...
@@ -50,6 +50,7 @@
# kde5_dir =
# qt5_dir =
import
inary.errors
import
configparser
import
io
import
os
...
...
@@ -60,8 +61,6 @@ import gettext
__trans
=
gettext
.
translation
(
'inary'
,
fallback
=
True
)
_
=
__trans
.
gettext
import
inary.errors
class
Error
(
inary
.
errors
.
Error
):
pass
...
...
@@ -130,7 +129,7 @@ class DirectoriesDefaults:
class
ConfigurationSection
(
object
):
"""ConfigurationSection class defines a section in the configuration
file, using defaults (above) as a fallback."""
file, using defaults (above) as a fallback."""
def
__init__
(
self
,
section
,
items
=
None
):
if
items
is
None
:
...
...
@@ -217,7 +216,8 @@ class ConfigurationFile(object):
# get, set and write_config methods added for manipulation of inary.conf file from Scom to solve bug #5668.
# Current ConfigParser does not keep the comments and white spaces, which we do not want for inary.conf. There
# are patches floating in the python sourceforge to add this feature. The write_config code is from python
# sourceforge tracker id: #1410680, modified a little to make it turn into a function.
# sourceforge tracker id: #1410680, modified a little to make it turn into
# a function.
def
get
(
self
,
section
,
option
):
try
:
...
...
@@ -338,7 +338,9 @@ class ConfigurationFile(object):
value
=
self
.
parser
.
get
(
sect
,
opt
)
# Fix continuations.
value
=
value
.
replace
(
"
\n
"
,
"
\n\t
"
)
output
.
write
(
"{0}{1}{2}
\n
"
.
format
(
opt
,
padded_vi
,
value
))
output
.
write
(
"{0}{1}{2}
\n
"
.
format
(
opt
,
padded_vi
,
value
))
written
.
append
((
sect
,
opt
))
# Copy across the new file.
fp
.
seek
(
0
)
...
...
inary/constants.py
Dosyayı görüntüle @
5c880a51
...
...
@@ -42,13 +42,15 @@ class _constant:
def
__setattr__
(
self
,
name
,
value
):
if
name
in
self
.
__dict__
:
raise
self
.
ConstError
(
_
(
"Can't rebind constant:
\'
{}
\'
"
)
.
format
(
name
))
raise
self
.
ConstError
(
_
(
"Can't rebind constant:
\'
{}
\'
"
)
.
format
(
name
))
# Binding an attribute once to a const is available
self
.
__dict__
[
name
]
=
value
def
__delattr__
(
self
,
name
):
if
name
in
self
.
__dict__
:
raise
self
.
ConstError
(
_
(
"Can't unbind constant:
\'
{}
\'
"
)
.
format
(
name
))
raise
self
.
ConstError
(
_
(
"Can't unbind constant:
\'
{}
\'
"
)
.
format
(
name
))
# we don't have an attribute by this name
raise
NameError
(
name
)
...
...
@@ -85,7 +87,8 @@ class Constants(metaclass=Singleton):
self
.
__c
.
ar_file_suffix
=
".a"
# directory suffixes for build
self
.
__c
.
work_dir_suffix
=
"/work"
# these, too, because we might wanna change 'em
# these, too, because we might wanna change 'em
self
.
__c
.
work_dir_suffix
=
"/work"
self
.
__c
.
install_dir_suffix
=
"/install"
self
.
__c
.
debug_dir_suffix
=
"/debug"
self
.
__c
.
debug_files_suffix
=
"/usr/lib/debug"
...
...
@@ -131,7 +134,6 @@ class Constants(metaclass=Singleton):
self
.
__c
.
check_func
=
"check"
self
.
__c
.
install_func
=
"install"
# file types
# FIXME: these seem redundant
self
.
__c
.
doc
=
"doc"
...
...
inary/db/itembyrepo.py
Dosyayı görüntüle @
5c880a51
...
...
@@ -13,7 +13,7 @@
#
import
gzip
import
inary.context
as
ctx
# Gettext Library
import
gettext
__trans
=
gettext
.
translation
(
'inary'
,
fallback
=
True
)
...
...
inary/fetcher.py
Dosyayı görüntüle @
5c880a51
This diff is collapsed.
Click to expand it.
inary/file.py
Dosyayı görüntüle @
5c880a51
...
...
@@ -19,6 +19,11 @@ we are just encapsulating a common pattern in our program, nothing big.
like all inary classes, it has been programmed in a non-restrictive way
"""
import
inary.util
import
inary.uri
import
inary.fetcher
import
inary.errors
import
inary.context
as
ctx
import
lzma
import
os
import
shutil
...
...
@@ -28,23 +33,20 @@ import gettext
__trans
=
gettext
.
translation
(
'inary'
,
fallback
=
True
)
_
=
__trans
.
gettext
import
inary.context
as
ctx
import
inary.errors
import
inary.fetcher
import
inary.uri
import
inary.util
class
AlreadyHaveException
(
inary
.
errors
.
Exception
):
def
__init__
(
self
,
url
,
localfile
):
inary
.
errors
.
Exception
.
__init__
(
self
,
_
(
"URL
\"
{0}
\"
already downloaded as
\"
{1}
\"
"
)
.
format
(
url
,
localfile
))
inary
.
errors
.
Exception
.
__init__
(
self
,
_
(
"URL
\"
{0}
\"
already downloaded as
\"
{1}
\"
"
)
.
format
(
url
,
localfile
))
self
.
url
=
url
self
.
localfile
=
localfile
class
NoSignatureFound
(
inary
.
errors
.
Exception
):
def
__init__
(
self
,
url
):
inary
.
errors
.
Exception
.
__init__
(
self
,
_
(
"No signature found for
\"
{}
\"
"
)
.
format
(
url
))
inary
.
errors
.
Exception
.
__init__
(
self
,
_
(
"No signature found for
\"
{}
\"
"
)
.
format
(
url
))
self
.
url
=
url
...
...
@@ -54,7 +56,8 @@ class Error(inary.errors.Error):
class
InvalidSignature
(
inary
.
errors
.
Error
):
def
__init__
(
self
,
url
):
inary
.
errors
.
Exception
.
__init__
(
self
,
_
(
"GPG Signature is invalid for
\"
{}
\"
"
)
.
format
(
url
))
inary
.
errors
.
Exception
.
__init__
(
self
,
_
(
"GPG Signature is invalid for
\"
{}
\"
"
)
.
format
(
url
))
self
.
url
=
url
...
...
@@ -98,7 +101,8 @@ class File:
def
decompress
(
localfile
,
compress
):
compress
=
File
.
choose_method
(
localfile
,
compress
)
if
compress
==
File
.
COMPRESSION_TYPE_XZ
:
open
(
localfile
[:
-
3
],
"w"
)
.
write
(
lzma
.
LZMAFile
(
localfile
)
.
read
()
.
decode
(
'utf-8'
))
open
(
localfile
[:
-
3
],
"w"
)
.
write
(
lzma
.
LZMAFile
(
localfile
)
.
read
()
.
decode
(
'utf-8'
))
localfile
=
localfile
[:
-
3
]
elif
compress
==
File
.
COMPRESSION_TYPE_BZ2
:
import
bz2
...
...
@@ -108,7 +112,7 @@ class File:
@staticmethod
def
download
(
uri
,
transfer_dir
=
"/tmp"
,
sha1sum
=
False
,
compress
=
None
,
sign
=
None
,
copylocal
=
False
,
pkgname
=
''
):
compress
=
None
,
sign
=
None
,
copylocal
=
False
,
pkgname
=
''
):
assert
isinstance
(
uri
,
inary
.
uri
.
URI
)
...
...
@@ -119,14 +123,19 @@ class File:
origfile
=
inary
.
util
.
join_path
(
transfer_dir
,
uri
.
filename
())
if
sha1sum
:
sha1filename
=
File
.
download
(
inary
.
uri
.
URI
(
uri
.
get_uri
()
+
'.sha1sum'
),
transfer_dir
)
sha1filename
=
File
.
download
(
inary
.
uri
.
URI
(
uri
.
get_uri
()
+
'.sha1sum'
),
transfer_dir
)
sha1f
=
open
(
sha1filename
)
newsha1
=
sha1f
.
read
()
.
split
(
"
\n
"
)[
0
]
if
uri
.
is_remote_file
()
or
copylocal
:
tmpfile
=
check_integrity
and
uri
.
filename
()
+
ctx
.
const
.
temporary_suffix
localfile
=
inary
.
util
.
join_path
(
transfer_dir
,
tmpfile
or
uri
.
filename
())
localfile
=
inary
.
util
.
join_path
(
transfer_dir
,
tmpfile
or
uri
.
filename
())
# TODO: code to use old .sha1sum file, is this a necessary optimization?
# oldsha1fn = localfile + '.sha1sum'
...
...
@@ -139,21 +148,27 @@ class File:
raise
AlreadyHaveException
(
uri
,
origfile
)
if
uri
.
is_remote_file
():
ctx
.
ui
.
info
(
_
(
"Fetching {}"
)
.
format
(
uri
.
get_uri
()),
verbose
=
True
)
inary
.
fetcher
.
fetch_url
(
uri
,
transfer_dir
,
ctx
.
ui
.
Progress
,
tmpfile
,
pkgname
)
ctx
.
ui
.
info
(
_
(
"Fetching {}"
)
.
format
(
uri
.
get_uri
()),
verbose
=
True
)
inary
.
fetcher
.
fetch_url
(
uri
,
transfer_dir
,
ctx
.
ui
.
Progress
,
tmpfile
,
pkgname
)
else
:
# copy to transfer dir
inary
.
fetcher
.
fetch_from_locale
(
uri
.
get_uri
(),
transfer_dir
,
destfile
=
localfile
)
inary
.
fetcher
.
fetch_from_locale
(
uri
.
get_uri
(),
transfer_dir
,
destfile
=
localfile
)
else
:
localfile
=
uri
.
get_uri
()
# TODO: use a special function here?
if
localfile
.
startswith
(
"file:///"
):
localfile
=
localfile
[
7
:]
localfile
=
localfile
[
7
:]
if
not
os
.
path
.
exists
(
localfile
):
raise
IOError
(
_
(
"File
\"
{}
\"
not found."
)
.
format
(
localfile
))
if
not
os
.
access
(
localfile
,
os
.
W_OK
):
oldfn
=
localfile
localfile
=
inary
.
util
.
join_path
(
transfer_dir
,
os
.
path
.
basename
(
localfile
))
localfile
=
inary
.
util
.
join_path
(
transfer_dir
,
os
.
path
.
basename
(
localfile
))
shutil
.
copy
(
oldfn
,
localfile
)
def
clean_temporary
():
...
...
@@ -171,7 +186,9 @@ class File:
if
sha1sum
:
if
inary
.
util
.
sha1_file
(
localfile
)
!=
newsha1
:
clean_temporary
()
raise
Error
(
_
(
"File integrity of
\"
{}
\"
compromised.
\n
localfile:{}
\n
newsha1: {}"
)
.
format
(
uri
,
inary
.
util
.
sha1_file
(
localfile
),
newsha1
))
raise
Error
(
_
(
"File integrity of
\"
{}
\"
compromised.
\n
localfile:{}
\n
newsha1: {}"
)
.
format
(
uri
,
inary
.
util
.
sha1_file
(
localfile
),
newsha1
))
if
check_integrity
:
shutil
.
move
(
localfile
,
origfile
)
...
...
@@ -197,7 +214,8 @@ class File:
raise
Error
(
_
(
"File mode must be either File.read or File.write"
))
if
uri
.
is_remote_file
():
if
self
.
mode
==
File
.
read
:
localfile
=
File
.
download
(
uri
,
transfer_dir
,
sha1sum
,
compress
,
sign
)
localfile
=
File
.
download
(
uri
,
transfer_dir
,
sha1sum
,
compress
,
sign
)
else
:
raise
Error
(
_
(
"Remote write not implemented."
))
else
:
...
...
@@ -216,7 +234,7 @@ class File:
"""returns the underlying file object"""
return
self
.
__file__
def
close
(
self
,
delete_transfer
=
False
):
# TODO: look this parameter
def
close
(
self
,
delete_transfer
=
False
):
# TODO: look this parameter
"""this method must be called at the end of operation"""
self
.
__file__
.
close
()
if
self
.
mode
==
File
.
write
:
...
...
@@ -233,7 +251,10 @@ class File:
import
bz2
compressed_file
=
self
.
localfile
+
".bz2"
compressed_files
.
append
(
compressed_file
)
bz2
.
BZ2File
(
compressed_file
,
"w"
)
.
write
(
open
(
self
.
localfile
)
.
read
())
bz2
.
BZ2File
(
compressed_file
,
"w"
)
.
write
(
open
(
self
.
localfile
)
.
read
())
if
self
.
sha1sum
:
sha1
=
inary
.
util
.
sha1_file
(
self
.
localfile
)
...
...
@@ -247,17 +268,22 @@ class File:
cs
.
close
()
if
self
.
sign
==
File
.
detached
:
if
inary
.
util
.
run_batch
(
'gpg --detach-sig '
+
self
.
localfile
)[
0
]:
raise
Error
(
_
(
"ERROR:
\'
gpg --detach-sig {}
\'
failed."
)
.
format
(
self
.
localfile
))
if
inary
.
util
.
run_batch
(
'gpg --detach-sig '
+
self
.
localfile
)[
0
]:
raise
Error
(
_
(
"ERROR:
\'
gpg --detach-sig {}
\'
failed."
)
.
format
(
self
.
localfile
))
for
compressed_file
in
compressed_files
:
if
inary
.
util
.
run_batch
(
'gpg --detach-sig '
+
compressed_file
)[
0
]:
raise
Error
(
_
(
"ERROR:
\'
gpg --detach-sig {}
\'
failed."
)
.
format
(
compressed_file
))
if
inary
.
util
.
run_batch
(
'gpg --detach-sig '
+
compressed_file
)[
0
]:
raise
Error
(
_
(
"ERROR:
\'
gpg --detach-sig {}
\'
failed."
)
.
format
(
compressed_file
))
@staticmethod
def
check_signature
(
uri
,
transfer_dir
,
sign
=
detached
):
if
sign
==
File
.
detached
:
try
:
sigfilename
=
File
.
download
(
inary
.
uri
.
URI
(
uri
+
'.sig'
),
transfer_dir
)
sigfilename
=
File
.
download
(
inary
.
uri
.
URI
(
uri
+
'.sig'
),
transfer_dir
)
except
KeyboardInterrupt
:
raise
except
IOError
:
# FIXME: what exception could we catch here, replace with that.
...
...
@@ -266,9 +292,13 @@ class File:
result
=
inary
.
util
.
run_batch
(
'gpg --verify '
+
sigfilename
)
if
ctx
.
config
.
values
.
general
.
ssl_verify
and
result
[
0
]:
ctx
.
ui
.
info
(
"Checking GPG Signature failed ('gpg --verify {}')"
.
format
(
sigfilename
),
color
=
'cyan'
)
ctx
.
ui
.
info
(
"Checking GPG Signature failed ('gpg --verify {}')"
.
format
(
sigfilename
),
color
=
'cyan'
)
ctx
.
ui
.
info
(
result
[
2
]
.
decode
(
"utf-8"
),
color
=
'faintcyan'
)
if
not
ctx
.
ui
.
confirm
(
"Would you like to skip checking gpg signature?"
):
if
not
ctx
.
ui
.
confirm
(
"Would you like to skip checking gpg signature?"
):
raise
InvalidSignature
(
uri
)
# everything is all right here
else
:
return
True
...
...
inary/mirrors.py
Dosyayı görüntüle @
5c880a51
...
...
@@ -21,9 +21,11 @@ import gettext
__trans
=
gettext
.
translation
(
'inary'
,
fallback
=
True
)
_
=
__trans
.
gettext
class
MirrorError
(
inary
.
errors
.
Error
):
pass
class
Mirrors
:
def
__init__
(
self
,
config
=
ctx
.
const
.
mirrors_conf
):
self
.
mirrors
=
{}
...
...
@@ -50,4 +52,5 @@ class Mirrors:
(
name
,
url
)
=
mirror
self
.
_add_mirror
(
name
,
url
)
else
:
raise
inary
.
errors
.
Error
(
_
(
'Mirrors file
\"
{}
\"
does not exist. Could not resolve
\"
mirrors://
\"
'
)
.
format
(
config
))
raise
inary
.
errors
.
Error
(
_
(
'Mirrors file
\"
{}
\"
does not exist. Could not resolve
\"
mirrors://
\"
'
)
.
format
(
config
))
inary/package.py
Dosyayı görüntüle @
5c880a51
...
...
@@ -15,22 +15,21 @@
"""package abstraction methods to add/remove files, extract control files"""
# Gettext Library
import
os.path
from
.
import
fetcher
import
inary.util
as
util
import
inary.data.files
import
inary.file
import
inary.data.metadata
import
inary.ui
import
inary.uri
import
inary.archive
as
archive
import
inary.context
as
ctx
import
inary.errors
import
gettext
__trans
=
gettext
.
translation
(
'inary'
,
fallback
=
True
)
_
=
__trans
.
gettext
import
inary.errors
import
inary.context
as
ctx
import
inary.archive
as
archive
import
inary.uri
import
inary.ui
import
inary.data.metadata
import
inary.file
import
inary.data.files
import
inary.util
as
util
from
.
import
fetcher
import
os.path
class
Error
(
inary
.
errors
.
Error
):
pass
...
...
@@ -62,7 +61,8 @@ class Package:
archive_name
=
ctx
.
const
.
install_tar
+
archive_suffix
return
archive_name
,
archive_format
def
__init__
(
self
,
packagefn
,
mode
=
'r'
,
format
=
None
,
tmp_dir
=
None
,
pkgname
=
''
,
no_fetch
=
False
):
def
__init__
(
self
,
packagefn
,
mode
=
'r'
,
format
=
None
,
tmp_dir
=
None
,
pkgname
=
''
,
no_fetch
=
False
):
self
.
filepath
=
packagefn
url
=
inary
.
uri
.
URI
(
packagefn
)
...
...
@@ -97,12 +97,12 @@ class Package:
self
.
tmp_dir
=
tmp_dir
or
ctx
.
config
.
tmp_dir
()
def
fetch_remote_file
(
self
,
url
,
pkgname
=
''
):
def
fetch_remote_file
(
self
,
url
,
pkgname
=
''
):
dest
=
ctx
.
config
.
cached_packages_dir
()
self
.
filepath
=
os
.
path
.
join
(
dest
,
url
.
filename
())
if
not
os
.
path
.
exists
(
self
.
filepath
):
try
:
inary
.
file
.
File
.
download
(
url
,
dest
,
pkgname
)
inary
.
file
.
File
.
download
(
url
,
dest
,
pkgname
)
except
fetcher
.
FetchError
:
# Bug 3465
if
ctx
.
get_option
(
'reinstall'
):
...
...
@@ -220,7 +220,8 @@ class Package:
#
# Also, tar.extract() doesn't write on symlinks... Not any
# more :).
if
os
.
path
.
isfile
(
tarinfo
.
name
)
or
os
.
path
.
islink
(
tarinfo
.
name
):
if
os
.
path
.
isfile
(
tarinfo
.
name
)
or
os
.
path
.
islink
(
tarinfo
.
name
):
try
:
os
.
unlink
(
tarinfo
.
name
)
except
OSError
as
e
:
...
...
@@ -229,7 +230,10 @@ class Package:
else
:
# Added for package-manager
if
tarinfo
.
name
.
endswith
(
".desktop"
):
ctx
.
ui
.
notify
(
inary
.
ui
.
desktopfile
,
logging
=
False
,
desktopfile
=
tarinfo
.
name
)
ctx
.
ui
.
notify
(
inary
.
ui
.
desktopfile
,
logging
=
False
,
desktopfile
=
tarinfo
.
name
)
tar
=
self
.
get_install_archive
()
...
...
@@ -252,7 +256,8 @@ class Package:
def
extract_inary_files
(
self
,
outdir
):
"""Extract INARY control files: metadata.xml, files.xml,
action scripts, etc."""
self
.
extract_files
([
ctx
.
const
.
metadata_xml
,
ctx
.
const
.
files_xml
],
outdir
)
self
.
extract_files
(
[
ctx
.
const
.
metadata_xml
,
ctx
.
const
.
files_xml
],
outdir
)
self
.
extract_dir
(
'config'
,
outdir
)
def
get_metadata
(
self
):
...
...
@@ -273,8 +278,8 @@ class Package:
def
pkg_dir
(
self
):
packageDir
=
self
.
metadata
.
package
.
name
+
'-'
\
+
self
.
metadata
.
package
.
version
+
'-'
\
+
self
.
metadata
.
package
.
release
+
self
.
metadata
.
package
.
version
+
'-'
\
+
self
.
metadata
.
package
.
release
return
os
.
path
.
join
(
ctx
.
config
.
packages_dir
(),
packageDir
)
...
...
@@ -283,7 +288,9 @@ class Package:
url
=
inary
.
uri
.
URI
(
packagefn
)
filepath
=
packagefn
if
url
.
is_remote_file
():
filepath
=
os
.
path
.
join
(
ctx
.
config
.
cached_packages_dir
(),
url
.
filename
())
filepath
=
os
.
path
.
join
(
ctx
.
config
.
cached_packages_dir
(),
url
.
filename
())
return
os
.
path
.
exists
(
filepath
)
and
filepath
else
:
return
filepath
inary/process.py
Dosyayı görüntüle @
5c880a51
...
...
@@ -12,6 +12,7 @@
import
multiprocessing
import
traceback
class
Process
(
multiprocessing
.
Process
):
def
__init__
(
self
,
*
args
,
**
kwargs
):
multiprocessing
.
Process
.
__init__
(
self
,
*
args
,
**
kwargs
)
...
...
@@ -31,4 +32,4 @@ class Process(multiprocessing.Process):
def
exception
(
self
):
if
self
.
_pconn
.
poll
():
self
.
_exception
=
self
.
_pconn
.
recv
()
return
self
.
_exception
\ No newline at end of file
return
self
.
_exception
inary/sysconf.py
Dosyayı görüntüle @
5c880a51
...
...
@@ -23,7 +23,8 @@ import gettext
__trans
=
gettext
.
translation
(
'inary'
,
fallback
=
True
)
_
=
__trans
.
gettext
sysconfdir
=
"/var/lib/inary/sysconf"
sysconfdir
=
"/var/lib/inary/sysconf"
def
getmtime
(
path
):
"""Get file or directory modify time"""
...
...
@@ -34,7 +35,7 @@ def getmtime(path):
def
getltime
(
name
):
"""Get last modify time from database"""
location
=
sysconfdir
+
"/{}"
.
format
(
name
)
location
=
sysconfdir
+
"/{}"
.
format
(
name
)
if
not
os
.
path
.
exists
(
sysconfdir
):
os
.
mkdir
(
sysconfdir
)
if
not
os
.
path
.
exists
(
location
):
...
...
@@ -44,7 +45,7 @@ def getltime(name):
def
setltime
(
name
,
value
):
"""Set last modify time to database"""
location
=
sysconfdir
+
"/{}"
.
format
(
name
)
location
=
sysconfdir
+
"/{}"
.
format
(
name
)
open
(
location
,
"w"
)
.
write
(
str
(
value
))
...
...
@@ -53,26 +54,27 @@ def t(name, path, command):
status
=
0
if
os
.
path
.
isdir
(
path
)
==
True
:
if
getltime
(
name
)
!=
getmtime
(
path
):
sys
.
stdout
.
write
(
"
\n\x1b
[33m "
+
\
_
(
"[-] Process triggering for "
)
+
\
sys
.
stdout
.
write
(
"
\n\x1b
[33m "
+
_
(
"[-] Process triggering for "
)
+
"
\x1b
[;0m{}"
.
format
(
name
))
status
=
os
.
system
(
command
+
" &>/dev/null"
)
setltime
(
name
,
getmtime
(
path
))
if
status
!=
0
:
sys
.
stdout
.
write
(
"
\r\x1b
[K
\x1b
[31;1m "
+
\
_
(
"[!] Triggering end with "
)
+
\
sys
.
stdout
.
write
(
"
\r\x1b
[K
\x1b
[31;1m "
+
_
(
"[!] Triggering end with "
)
+
"
\x1b
[;0m{}"
.
format
(
status
))
else
:
sys
.
stdout
.
write
(
"
\r\x1b
[K
\x1b
[32;1m "
+
\
_
(
"[+] Process triggered for "
+
\
"
\x1b
[;0m{}"
.
format
(
name
)))
sys
.
stdout
.
write
(
"
\r\x1b
[K
\x1b
[32;1m "
+
_
(
"[+] Process triggered for "
+
"
\x1b
[;0m{}"
.
format
(
name
)))
def
t_r
(
name
,
path
,
command
):
"""main trigger handler with recursive"""
for
i
in
os
.
listdir
(
path
):
if
os
.
path
.
isdir
(
"{}/{}"
.
format
(
path
,
i
)):
t
(
"{}-{}"
.
format
(
name
,
i
),
"{}/{}"
.
format
(
path
,
i
),
"{}{}"
.
format
(
command
,
i
))
if
os
.
path
.
isdir
(
"{}/{}"
.
format
(
path
,
i
)):
t
(
"{}-{}"
.
format
(
name
,
i
),
"{}/{}"
.
format
(
path
,
i
),
"{}{}"
.
format
(
command
,
i
))
def
proceed
(
force
=
False
):
...
...
@@ -82,18 +84,23 @@ def proceed(force=False):
if
force
:
os
.
system
(
"rm -rf {}"
.
format
(
sysconfdir
))
t
(
"fonts"
,
"/usr/share/fonts"
,
"fc-cache -f"
)
t
(
"glib-schema"
,
"/usr/share/glib-2.0/schemas/"
,
"glib-compile-schemas /usr/share/glib-2.0/schemas/"
)
t
(
"glib-schema"
,
"/usr/share/glib-2.0/schemas/"
,
"glib-compile-schemas /usr/share/glib-2.0/schemas/"
)
t_r
(
"icon"
,
"/usr/share/icons"
,
"gtk-update-icon-cache -t -f /usr/share/icons/"
)
t
(
"desktop-database"
,
"/usr/share/applications"
,
"update-desktop-database /usr/share/applications"
)
t
(
"desktop-database"
,
"/usr/share/applications"
,
"update-desktop-database /usr/share/applications"
)
t
(
"mandb"
,
"/usr/share/man"
,
"mandb cache-update"
)
t_r
(
"linux"
,
"/lib/modules/"
,
"depmod -a "
)
t
(
"gdk-pixbuf"
,
"/usr/lib/gdk-pixbuf-2.0/"
,
"gdk-pixbuf-query-loaders --update-cache"
)
t
(
"gdk-pixbuf"
,
"/usr/lib/gdk-pixbuf-2.0/"
,
"gdk-pixbuf-query-loaders --update-cache"
)
t
(
"mime"
,
"/usr/share/mime"
,
"update-mime-database /usr/share/mime"
)
t
(
"dbus"
,
"/usr/share/dbus-1"
,
"dbus-send --system --type=method_call --dest=org.freedesktop.DBus / org.freedesktop.DBUS.ReloadConfig"
)
t
(
"eudev"
,
"/lib/udev/"
,
"udevadm control --reload"
)
t
(
"gio-modules"
,
"/usr/lib/gio/modules/"
,
"gio-querymodules /usr/lib/gio/modules/"
)
t
(
"gio-modules"
,
"/usr/lib/gio/modules/"
,
"gio-querymodules /usr/lib/gio/modules/"
)
t
(
"appstream"
,
"/var/cache/app-info"
,
"appstreamcli refresh-cache --force"
)
t
(
"ca-certficates"
,
"/etc/ssl/certs"
,
"update-ca-certificates --fresh"
)
t
(
"cracklib"
,
"/usr/share/cracklib/"
,
"create-cracklib-dict /usr/share/cracklib/*"
)
t
(
"cracklib"
,
"/usr/share/cracklib/"
,
"create-cracklib-dict /usr/share/cracklib/*"
)
sys
.
stdout
.
write
(
"
\n
"
)
inary/trigger.py
Dosyayı görüntüle @
5c880a51
...
...
@@ -21,11 +21,11 @@ import inary.util as util
class
Trigger
:
def
__init__
(
self
):
self
.
specdir
=
None
self
.
specdir
=
None
self
.
Locals
=
None
self
.
Globals
=
None
self
.
postscript
=
None
self
.
missing_postOps
=
False
self
.
missing_postOps
=
False
def
load_script
(
self
):
"""Compiles and executes the script"""
...
...
@@ -51,7 +51,7 @@ class Trigger:
buf
=
open
(
fname
)
.
read
()
return
compile
(
buf
,
fname
,
"exec"
)
else
:
self
.
missing_postOps
=
True
self
.
missing_postOps
=
True
return
None
def
run_command
(
self
,
func
):
...
...
@@ -59,20 +59,28 @@ class Trigger:
if
not
self
.
missing_postOps
:
curDir
=
os
.
getcwd
()
os
.
chdir
(
self
.
specdir
)
cmd_extra
=
""
#FIXME: translate support needed
cmd_extra
=
""
#
FIXME: translate support needed
if
ctx
.
config
.
get_option
(
'debug'
):
ctx
.
ui
.
info
(
util
.
colorize
(
"Running => {}"
,
'brightgreen'
)
.
format
(
util
.
colorize
(
func
,
"brightyellow"
)))
ctx
.
ui
.
info
(
util
.
colorize
(
"Running => {}"
,
'brightgreen'
)
.
format
(
util
.
colorize
(
func
,
"brightyellow"
)))
else
:
cmd_extra
=
" > /dev/null"
ret_val
=
os
.
system
(
'python3 -c
\'
import postoperations
\n
if(hasattr(postoperations,"{0}")):
\n
postoperations.{0}()
\'
'
.
format
(
func
)
+
cmd_extra
)
cmd_extra
=
" > /dev/null"
ret_val
=
os
.
system
(
'python3 -c
\'
import postoperations
\n
if(hasattr(postoperations,"{0}")):
\n
postoperations.{0}()
\'
'
.
format
(
func
)
+
cmd_extra
)
os
.
chdir
(
curDir
)
return
(
ret_val
==
0
)
return
(
ret_val
==
0
)
else
:
return
0
def
preinstall
(
self
,
specdir
):
self
.
specdir
=
specdir
self
.
specdir
=
specdir
self
.
postscript
=
util
.
join_path
(
self
.
specdir
,
ctx
.
const
.
postops
)
self
.
load_script
()
retval
=
self
.
run_command
(
"preInstall"
)
...
...
@@ -80,19 +88,19 @@ class Trigger:
return
retval
def
postinstall
(
self
,
specdir
):
self
.
specdir
=
specdir
self
.
specdir
=
specdir
self
.
postscript
=
util
.
join_path
(
self
.
specdir
,
ctx
.
const
.
postops
)
self
.
load_script
()
return
self
.
run_command
(
"postInstall"
)
def
postremove
(
self
,
specdir
):
self
.
specdir
=
specdir
self
.
specdir
=
specdir
self
.
postscript
=
util
.
join_path
(
self
.
specdir
,
ctx
.
const
.
postops
)
self
.
load_script
()
return
self
.
run_command
(
"postRemove"
)
def
preremove
(
self
,
specdir
):
self
.
specdir
=
specdir
self
.
specdir
=
specdir
self
.
postscript
=
util
.
join_path
(
self
.
specdir
,
ctx
.
const
.
postops
)
self
.
load_script
()
return
self
.
run_command
(
"preRemove"
)
inary/ui.py
Dosyayı görüntüle @
5c880a51
...
...
@@ -84,7 +84,7 @@ class UI(object):
"""ask the user to choose from a list of alternatives"""
pass
def
confirm
(
self
,
msg
,
invert
=
False
):
def
confirm
(
self
,
msg
,
invert
=
False
):
"""ask the user to confirm question"""
pass
...
...
inary/util.py
Dosyayı görüntüle @
5c880a51
This diff is collapsed.
Click to expand it.
inary/version.py
Dosyayı görüntüle @
5c880a51
...
...
@@ -14,12 +14,12 @@
"""version structure"""
import
inary.errors
import
gettext
__trans
=
gettext
.
translation
(
'inary'
,
fallback
=
True
)
_
=
__trans
.
gettext
import
inary.errors
# Basic rule is:
# p > (no suffix) > m > rc > pre > beta > alpha
...
...
@@ -55,19 +55,21 @@ def make_version(version):
for
keyword
,
value
in
__keywords
:
if
suffix
.
startswith
(
keyword
):
return
list
(
map
(
__make_version_item
,
ver
.
split
(
"."
))),
value
,
\
list
(
map
(
__make_version_item
,
suffix
[
len
(
keyword
):]
.
split
(
"."
)))
list
(
map
(
__make_version_item
,
suffix
[
len
(
keyword
):]
.
split
(
"."
)))
else
:
# Probably an invalid version string. Reset ver string
# to raise an exception in __make_version_item function.
ver
=
""
else
:
return
list
(
map
(
__make_version_item
,
ver
.
split
(
"."
))),
0
,
\
list
(
map
(
__make_version_item
,
suffix
.
split
(
"."
)))
list
(
map
(
__make_version_item
,
suffix
.
split
(
"."
)))
return
list
(
map
(
__make_version_item
,
ver
.
split
(
"."
))),
0
,
[(
0
,
None
)]
except
ValueError
:
raise
InvalidVersionError
(
_
(
"Invalid version string: '{}'"
)
.
format
(
version
))
raise
InvalidVersionError
(
_
(
"Invalid version string: '{}'"
)
.
format
(
version
))
class
Version
(
object
):
...
...
@@ -91,9 +93,11 @@ class Version(object):
def
compare
(
self
,
ver
):
# In old code it was written with cmp().
if
isinstance
(
ver
,
str
):
return
(
self
.
__version
>
make_version
(
ver
))
-
(
self
.
__version
<
make_version
(
ver
))
return
(
self
.
__version
>
make_version
(
ver
))
-
\
(
self
.
__version
<
make_version
(
ver
))
return
(
self
.
__version
>
ver
.
__version
)
-
(
self
.
__version
<
ver
.
__version
)
return
(
self
.
__version
>
ver
.
__version
)
-
\
(
self
.
__version
<
ver
.
__version
)
def
__lt__
(
self
,
rhs
):
if
isinstance
(
rhs
,
str
):
...
...
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