bits-installer 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/bin/bits +20 -0
- data/ext/apt/Cache.cpp +68 -0
- data/ext/apt/Cache.h +18 -0
- data/ext/apt/Package.cpp +63 -0
- data/ext/apt/Package.h +30 -0
- data/ext/apt/PackageVersion.cpp +49 -0
- data/ext/apt/PackageVersion.h +24 -0
- data/ext/apt/apt_ext.cpp +38 -0
- data/ext/apt/apt_ext.h +4 -0
- data/ext/apt/extconf.rb +12 -0
- data/lib/bits/backend/join.rb +26 -0
- data/lib/bits/backend/local.rb +24 -0
- data/lib/bits/backend.rb +9 -0
- data/lib/bits/bit.rb +33 -0
- data/lib/bits/bit_declaration.rb +143 -0
- data/lib/bits/bit_reader/local.rb +13 -0
- data/lib/bits/bit_reader.rb +7 -0
- data/lib/bits/command.rb +48 -0
- data/lib/bits/command_provider.rb +39 -0
- data/lib/bits/commands/install.rb +75 -0
- data/lib/bits/commands/remove.rb +35 -0
- data/lib/bits/commands/show.rb +49 -0
- data/lib/bits/commands/sync.rb +34 -0
- data/lib/bits/exceptions.rb +12 -0
- data/lib/bits/execute_context.rb +24 -0
- data/lib/bits/external_interface.rb +204 -0
- data/lib/bits/logging.rb +24 -0
- data/lib/bits/package.rb +27 -0
- data/lib/bits/package_proxy.rb +61 -0
- data/lib/bits/provider/apt.rb +75 -0
- data/lib/bits/provider/homebrew.rb +59 -0
- data/lib/bits/provider/portage.rb +69 -0
- data/lib/bits/provider/python.rb +86 -0
- data/lib/bits/provider.rb +77 -0
- data/lib/bits/provider_reporting.rb +24 -0
- data/lib/bits/repository.rb +118 -0
- data/lib/bits/spawn.rb +89 -0
- data/lib/bits/user.rb +27 -0
- data/lib/bits/version.rb +3 -0
- data/lib/bits.rb +156 -0
- data/lib/libexec/bits-python +157 -0
- metadata +153 -0
data/bin/bits
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
if __FILE__ == $0
|
4
|
+
lib = File.expand_path File.join('..', '..', 'lib'), $0
|
5
|
+
|
6
|
+
if File.file? File.join(lib, 'bits.rb')
|
7
|
+
$:.insert 0, lib
|
8
|
+
bin = File.expand_path File.join('..', 'bin'), lib
|
9
|
+
ENV['PATH']="#{bin}:#{ENV['PATH']}"
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
begin
|
14
|
+
require 'bits'
|
15
|
+
rescue LoadError
|
16
|
+
require 'rubygems'
|
17
|
+
require 'bits'
|
18
|
+
end
|
19
|
+
|
20
|
+
exit Bits::main(ARGV)
|
data/ext/apt/Cache.cpp
ADDED
@@ -0,0 +1,68 @@
|
|
1
|
+
#include "Cache.h"
|
2
|
+
|
3
|
+
#include <apt-pkg/cachefile.h>
|
4
|
+
#include <apt-pkg/cacheset.h>
|
5
|
+
|
6
|
+
#include "PackageVersion.h"
|
7
|
+
#include "Package.h"
|
8
|
+
|
9
|
+
Apt::PackageVersion *to_package_version(pkgCache::VerIterator iterator)
|
10
|
+
{
|
11
|
+
std::string version(iterator.VerStr());
|
12
|
+
std::string arch(iterator.Arch());
|
13
|
+
std::string section(iterator.Section());
|
14
|
+
return new Apt::PackageVersion(version, arch, section);
|
15
|
+
}
|
16
|
+
|
17
|
+
Rice::Array Apt::Cache::policy(std::string name)
|
18
|
+
{
|
19
|
+
Rice::Array result;
|
20
|
+
|
21
|
+
pkgCacheFile CacheFile;
|
22
|
+
pkgCache *Cache = CacheFile.GetPkgCache();
|
23
|
+
pkgPolicy *Plcy = CacheFile.GetPolicy();
|
24
|
+
pkgSourceList *SrcList = CacheFile.GetSourceList();
|
25
|
+
|
26
|
+
if (Cache == NULL || Plcy == NULL || SrcList == NULL)
|
27
|
+
{
|
28
|
+
return Qnil;
|
29
|
+
}
|
30
|
+
|
31
|
+
APT::CacheSetHelper helper(true, GlobalError::NOTICE);
|
32
|
+
APT::PackageList pkgset = APT::PackageList::FromString(CacheFile, name, helper);
|
33
|
+
|
34
|
+
for (APT::PackageList::const_iterator Pkg = pkgset.begin(); Pkg != pkgset.end(); ++Pkg)
|
35
|
+
{
|
36
|
+
std::string full_name = Pkg.FullName(true);
|
37
|
+
Rice::Object current_version;
|
38
|
+
Rice::Object candidate_version;
|
39
|
+
|
40
|
+
if (Pkg->CurrentVer != 0) {
|
41
|
+
pkgCache::VerIterator current = Pkg.CurrentVer();
|
42
|
+
current_version = to_ruby(to_package_version(current));
|
43
|
+
}
|
44
|
+
|
45
|
+
pkgCache::VerIterator candidate = Plcy->GetCandidateVer(Pkg);
|
46
|
+
|
47
|
+
if (candidate.end() != true) {
|
48
|
+
candidate_version = to_ruby(to_package_version(candidate));
|
49
|
+
}
|
50
|
+
|
51
|
+
Apt::Package *package = new Apt::Package(
|
52
|
+
full_name, current_version, candidate_version
|
53
|
+
);
|
54
|
+
|
55
|
+
result.push(to_ruby(package));
|
56
|
+
}
|
57
|
+
|
58
|
+
return result;
|
59
|
+
}
|
60
|
+
|
61
|
+
|
62
|
+
extern "C"
|
63
|
+
void Init_Apt_Cache(Rice::Module parent)
|
64
|
+
{
|
65
|
+
Rice::Module rb_mAptCache = Rice::define_module_under(parent, "Cache")
|
66
|
+
.define_singleton_method("policy", &Apt::Cache::policy, Rice::Arg("name"))
|
67
|
+
;
|
68
|
+
}
|
data/ext/apt/Cache.h
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
#ifndef __APT_CACHE__H__
|
2
|
+
#define __APT_CACHE__H__
|
3
|
+
|
4
|
+
#include <rice/Module.hpp>
|
5
|
+
#include <rice/Array.hpp>
|
6
|
+
|
7
|
+
namespace Apt {
|
8
|
+
namespace Cache {
|
9
|
+
/**
|
10
|
+
* Interface similar to apt-cache policy.
|
11
|
+
*/
|
12
|
+
Rice::Array policy(std::string name);
|
13
|
+
} /* Cache */
|
14
|
+
} /* Apt */
|
15
|
+
|
16
|
+
extern "C" void Init_Apt_Cache(Rice::Module parent);
|
17
|
+
|
18
|
+
#endif /* __APT_CACHE__H__ */
|
data/ext/apt/Package.cpp
ADDED
@@ -0,0 +1,63 @@
|
|
1
|
+
#include "Package.h"
|
2
|
+
#include "PackageVersion.h"
|
3
|
+
|
4
|
+
#include <rice/Class.hpp>
|
5
|
+
#include <rice/Constructor.hpp>
|
6
|
+
|
7
|
+
namespace Apt {
|
8
|
+
Package::Package(
|
9
|
+
std::string name,
|
10
|
+
Rice::Object current,
|
11
|
+
Rice::Object candidate
|
12
|
+
)
|
13
|
+
: name_(name)
|
14
|
+
, current_(current)
|
15
|
+
, candidate_(candidate)
|
16
|
+
{
|
17
|
+
}
|
18
|
+
|
19
|
+
Package::~Package()
|
20
|
+
{ }
|
21
|
+
|
22
|
+
std::string Package::name()
|
23
|
+
{
|
24
|
+
return name_;
|
25
|
+
}
|
26
|
+
|
27
|
+
Rice::Object Package::current()
|
28
|
+
{
|
29
|
+
return current_;
|
30
|
+
}
|
31
|
+
|
32
|
+
Rice::Object Package::candidate()
|
33
|
+
{
|
34
|
+
return candidate_;
|
35
|
+
}
|
36
|
+
|
37
|
+
std::string Package::to_s()
|
38
|
+
{
|
39
|
+
std::stringstream ss;
|
40
|
+
|
41
|
+
ss << "<Package"
|
42
|
+
<< " name=" << name_
|
43
|
+
<< " current=" << current_
|
44
|
+
<< " candidate=" << candidate_
|
45
|
+
<< ">";
|
46
|
+
|
47
|
+
return ss.str();
|
48
|
+
}
|
49
|
+
} /* Apt */
|
50
|
+
|
51
|
+
extern "C"
|
52
|
+
void Init_Apt_Package(Rice::Module parent)
|
53
|
+
{
|
54
|
+
Rice::Class rb_cPackage =
|
55
|
+
Rice::define_class_under<Apt::Package>(parent, "Package")
|
56
|
+
.define_constructor(Rice::Constructor<Apt::Package, std::string, Rice::Object, Rice::Object>())
|
57
|
+
.define_method("name", &Apt::Package::name)
|
58
|
+
.define_method("current", &Apt::Package::current)
|
59
|
+
.define_method("candidate", &Apt::Package::candidate)
|
60
|
+
.define_method("current", &Apt::Package::current)
|
61
|
+
.define_method("to_s", &Apt::Package::to_s)
|
62
|
+
;
|
63
|
+
}
|
data/ext/apt/Package.h
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
#ifndef __APT_PACKAGE__H__
|
2
|
+
#define __APT_PACKAGE__H__
|
3
|
+
|
4
|
+
#include <rice/Object.hpp>
|
5
|
+
#include <rice/Module.hpp>
|
6
|
+
|
7
|
+
|
8
|
+
namespace Apt {
|
9
|
+
class Package {
|
10
|
+
public:
|
11
|
+
Package(
|
12
|
+
std::string name,
|
13
|
+
Rice::Object current,
|
14
|
+
Rice::Object candidate
|
15
|
+
);
|
16
|
+
~Package();
|
17
|
+
std::string name();
|
18
|
+
Rice::Object current();
|
19
|
+
Rice::Object candidate();
|
20
|
+
std::string to_s();
|
21
|
+
private:
|
22
|
+
std::string name_;
|
23
|
+
Rice::Object current_;
|
24
|
+
Rice::Object candidate_;
|
25
|
+
};
|
26
|
+
} /* Apt */
|
27
|
+
|
28
|
+
extern "C" void Init_Apt_Package(Rice::Module parent);
|
29
|
+
|
30
|
+
#endif /* __APT_PACKAGE__H__ */
|
@@ -0,0 +1,49 @@
|
|
1
|
+
#include "PackageVersion.h"
|
2
|
+
|
3
|
+
#include <rice/Constructor.hpp>
|
4
|
+
|
5
|
+
namespace Apt {
|
6
|
+
PackageVersion::PackageVersion(std::string version, std::string arch, std::string section)
|
7
|
+
: version_(version)
|
8
|
+
, arch_(arch)
|
9
|
+
, section_(section)
|
10
|
+
{
|
11
|
+
}
|
12
|
+
|
13
|
+
PackageVersion::~PackageVersion()
|
14
|
+
{ }
|
15
|
+
|
16
|
+
std::string PackageVersion::version()
|
17
|
+
{
|
18
|
+
return version_;
|
19
|
+
}
|
20
|
+
|
21
|
+
std::string PackageVersion::arch()
|
22
|
+
{
|
23
|
+
return arch_;
|
24
|
+
}
|
25
|
+
|
26
|
+
std::string PackageVersion::section()
|
27
|
+
{
|
28
|
+
return section_;
|
29
|
+
}
|
30
|
+
|
31
|
+
std::string PackageVersion::to_s() {
|
32
|
+
std::stringstream ss;
|
33
|
+
ss << "<PackageVersion version=" << version_ << ">";
|
34
|
+
return ss.str();
|
35
|
+
}
|
36
|
+
} /* Apt */
|
37
|
+
|
38
|
+
extern "C"
|
39
|
+
void Init_Apt_PackageVersion(Rice::Module parent)
|
40
|
+
{
|
41
|
+
Rice::Class rb_cPackageVersion =
|
42
|
+
Rice::define_class_under<Apt::PackageVersion>(parent, "PackageVersion")
|
43
|
+
.define_constructor(Rice::Constructor<Apt::PackageVersion, std::string, std::string, std::string>())
|
44
|
+
.define_method("version", &Apt::PackageVersion::version)
|
45
|
+
.define_method("arch", &Apt::PackageVersion::arch)
|
46
|
+
.define_method("section", &Apt::PackageVersion::section)
|
47
|
+
.define_method("to_s", &Apt::PackageVersion::to_s)
|
48
|
+
;
|
49
|
+
}
|
@@ -0,0 +1,24 @@
|
|
1
|
+
#ifndef __APT_PACKAGE_VERSION__H__
|
2
|
+
#define __APT_PACKAGE_VERSION__H__
|
3
|
+
|
4
|
+
#include <rice/Module.hpp>
|
5
|
+
|
6
|
+
namespace Apt {
|
7
|
+
class PackageVersion {
|
8
|
+
public:
|
9
|
+
PackageVersion(std::string version, std::string arch, std::string section);
|
10
|
+
~PackageVersion();
|
11
|
+
std::string version();
|
12
|
+
std::string arch();
|
13
|
+
std::string section();
|
14
|
+
std::string to_s();
|
15
|
+
private:
|
16
|
+
std::string version_;
|
17
|
+
std::string arch_;
|
18
|
+
std::string section_;
|
19
|
+
};
|
20
|
+
} /* Apt */
|
21
|
+
|
22
|
+
extern "C" void Init_Apt_PackageVersion(Rice::Module parent);
|
23
|
+
|
24
|
+
#endif /* __APT_PACKAGE_VERSION__H__ */
|
data/ext/apt/apt_ext.cpp
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
#include "apt_ext.h"
|
2
|
+
|
3
|
+
#include <rice/Module.hpp>
|
4
|
+
|
5
|
+
#include <apt-pkg/init.h>
|
6
|
+
|
7
|
+
#include "Cache.h"
|
8
|
+
#include "PackageVersion.h"
|
9
|
+
#include "Package.h"
|
10
|
+
|
11
|
+
|
12
|
+
namespace Apt {
|
13
|
+
bool initialize()
|
14
|
+
{
|
15
|
+
if (!pkgInitConfig(*_config)) {
|
16
|
+
return false;
|
17
|
+
}
|
18
|
+
|
19
|
+
if (!pkgInitSystem(*_config, _system)) {
|
20
|
+
return false;
|
21
|
+
}
|
22
|
+
|
23
|
+
return true;
|
24
|
+
}
|
25
|
+
} /* Apt */
|
26
|
+
|
27
|
+
|
28
|
+
extern "C"
|
29
|
+
void Init_apt_ext()
|
30
|
+
{
|
31
|
+
Rice::Module rb_mApt = Rice::define_module("Apt")
|
32
|
+
.define_singleton_method("initialize", &Apt::initialize)
|
33
|
+
;
|
34
|
+
|
35
|
+
Init_Apt_Cache(rb_mApt);
|
36
|
+
Init_Apt_Package(rb_mApt);
|
37
|
+
Init_Apt_PackageVersion(rb_mApt);
|
38
|
+
}
|
data/ext/apt/apt_ext.h
ADDED
data/ext/apt/extconf.rb
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'bits/backend'
|
2
|
+
require 'bits/logging'
|
3
|
+
require 'bits/exceptions'
|
4
|
+
|
5
|
+
module Bits
|
6
|
+
class JoinBackend < Backend
|
7
|
+
include Bits::Logging
|
8
|
+
|
9
|
+
def initialize(backends)
|
10
|
+
@backends = backends
|
11
|
+
end
|
12
|
+
|
13
|
+
# no need to fetch
|
14
|
+
def fetch(atom)
|
15
|
+
@backends.each do |backend|
|
16
|
+
begin
|
17
|
+
return backend.fetch atom
|
18
|
+
rescue MissingBit
|
19
|
+
next
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
raise MissingBit.new atom
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'bits/backend'
|
2
|
+
require 'bits/logging'
|
3
|
+
require 'bits/exceptions'
|
4
|
+
|
5
|
+
require 'bits/bit_reader/local'
|
6
|
+
|
7
|
+
module Bits
|
8
|
+
class LocalBackend < Backend
|
9
|
+
include Bits::Logging
|
10
|
+
|
11
|
+
def initialize(path, ext='yml')
|
12
|
+
@path = path
|
13
|
+
@ext = ext
|
14
|
+
end
|
15
|
+
|
16
|
+
# no need to fetch
|
17
|
+
def fetch(atom)
|
18
|
+
path = File.join @path, "#{atom}.#{@ext}"
|
19
|
+
raise MissingBit.new atom unless File.file? path
|
20
|
+
log.debug "bit from local path: #{path}"
|
21
|
+
BitReaderLocal.new path
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
data/lib/bits/backend.rb
ADDED
data/lib/bits/bit.rb
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
module Bits
|
2
|
+
# Class containing data for a single bit.
|
3
|
+
class Bit
|
4
|
+
attr_accessor :atom, :dependencies
|
5
|
+
|
6
|
+
def initialize(atom, provider_data, dependencies)
|
7
|
+
@atom = atom
|
8
|
+
@provider_data = provider_data
|
9
|
+
@dependencies = dependencies
|
10
|
+
end
|
11
|
+
|
12
|
+
def to_s
|
13
|
+
"<Bit atom=#{atom} dependencies=#{dependencies.inspect} provider_data=#{@provider_data.inspect}>"
|
14
|
+
end
|
15
|
+
|
16
|
+
def has_provider?(provider_id)
|
17
|
+
@provider_data.has_key? provider_id
|
18
|
+
end
|
19
|
+
|
20
|
+
def get_provider_data(provider_id)
|
21
|
+
unless has_provider? provider_id
|
22
|
+
raise "#{self} not provided by #{provider_id}"
|
23
|
+
end
|
24
|
+
|
25
|
+
@provider_data[provider_id]
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.eval(reader, atom)
|
29
|
+
decl = BitDeclaration.eval reader
|
30
|
+
self.new atom, decl.provider_data, decl.dependencies
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,143 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
|
3
|
+
module Bits
|
4
|
+
class BitReference
|
5
|
+
attr_reader :atom
|
6
|
+
|
7
|
+
def initialize(atom)
|
8
|
+
@atom = atom
|
9
|
+
end
|
10
|
+
|
11
|
+
def to_s
|
12
|
+
"<BitReference #{@atom}>"
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
class BitParameters
|
17
|
+
attr_reader :parameters
|
18
|
+
|
19
|
+
def initialize(parameters)
|
20
|
+
@parameters = parameters
|
21
|
+
end
|
22
|
+
|
23
|
+
def to_s
|
24
|
+
"<BitParameters #{@parameters}>"
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
# Class used to manage state of a bit declaration file.
|
29
|
+
class BitDeclaration
|
30
|
+
attr_accessor :provider_data, :dependencies
|
31
|
+
|
32
|
+
def initialize(data)
|
33
|
+
@provider_data = parse_provider_data data
|
34
|
+
@dependencies = parse_dependencies data
|
35
|
+
end
|
36
|
+
|
37
|
+
def parse_provider_data(data)
|
38
|
+
h = Hash.new
|
39
|
+
|
40
|
+
provided_for = data[:provided_for]
|
41
|
+
provided_by = data[:provided_by]
|
42
|
+
|
43
|
+
unless provided_by.nil?
|
44
|
+
unless provided_by.kind_of? Hash
|
45
|
+
raise "Expected Hash but got '#{provided_by.inspect}'"
|
46
|
+
end
|
47
|
+
|
48
|
+
provided_by.each do |provider_id, parameters|
|
49
|
+
unless parameters.kind_of? Hash
|
50
|
+
raise "Expected Hash but got '#{parameters.inspect}'"
|
51
|
+
end
|
52
|
+
|
53
|
+
unless provider_id.kind_of? Symbol
|
54
|
+
raise "Expected Symbol but got '#{provider_id.inspect}'"
|
55
|
+
end
|
56
|
+
|
57
|
+
unless h[provider_id].nil?
|
58
|
+
raise "Provider already defined '#{provider_id}'"
|
59
|
+
end
|
60
|
+
|
61
|
+
h[provider_id] = BitParameters.new parameters
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
unless provided_for.nil?
|
66
|
+
unless provided_for.kind_of? Hash
|
67
|
+
raise "Expected Hash but got '#{provided_for.inspect}'"
|
68
|
+
end
|
69
|
+
|
70
|
+
provided_for.each do |provider_id, reference|
|
71
|
+
unless reference.kind_of? String
|
72
|
+
raise "Expected String but got '#{reference.inspect}'"
|
73
|
+
end
|
74
|
+
|
75
|
+
unless provider_id.kind_of? Symbol
|
76
|
+
raise "Expected Symbol but got '#{provider_id.inspect}'"
|
77
|
+
end
|
78
|
+
|
79
|
+
unless h[provider_id].nil?
|
80
|
+
raise "Provider already defined '#{provider_id}'"
|
81
|
+
end
|
82
|
+
|
83
|
+
h[provider_id] = BitReference.new reference
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
h
|
88
|
+
end
|
89
|
+
|
90
|
+
def parse_dependencies(data)
|
91
|
+
h = Hash.new
|
92
|
+
|
93
|
+
depends = data[:depends]
|
94
|
+
|
95
|
+
unless depends.nil?
|
96
|
+
unless depends.kind_of? Array
|
97
|
+
raise "Expected Array but got '#{depends.inspect}'"
|
98
|
+
end
|
99
|
+
|
100
|
+
depends.each do |item|
|
101
|
+
unless item.kind_of? Hash
|
102
|
+
raise "Expected Hash but got '#{item.inspect}'"
|
103
|
+
end
|
104
|
+
|
105
|
+
atom = item[:atom]
|
106
|
+
|
107
|
+
if atom.nil?
|
108
|
+
raise "Expected :atom to be not null in dependency"
|
109
|
+
end
|
110
|
+
|
111
|
+
h[atom] = BitParameters.new item
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
h
|
116
|
+
end
|
117
|
+
|
118
|
+
# Used inside bit declaration.
|
119
|
+
def provided_by(provider_id, params={})
|
120
|
+
@provider_data[provider_id] = BitParameters.new params
|
121
|
+
end
|
122
|
+
|
123
|
+
# Used inside bit declaration.
|
124
|
+
# Defines that the following set of providers are provided by another bit.
|
125
|
+
def provided_for(params={})
|
126
|
+
params.each do |key, value|
|
127
|
+
key = key.to_sym
|
128
|
+
@provider_data[key] = BitReference.new value
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
def depends(atom, params={})
|
133
|
+
@dependencies[atom] = params
|
134
|
+
end
|
135
|
+
|
136
|
+
def self.eval(reader)
|
137
|
+
data = YAML.load reader.read
|
138
|
+
decl = self.new data
|
139
|
+
decl
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
end
|