Browse Source

Added Debian to local installer

I couldn't write it in bash, so I had to go with Python.
Eventually I'll rewrite locinst.sh to be almost fully Python.
master
parent
commit
64e06be91c
3 changed files with 164 additions and 2 deletions
  1. 1
    0
      .gitignore
  2. 152
    0
      scripts/locinst.py
  3. 11
    2
      scripts/locinst.sh

+ 1
- 0
.gitignore View File

@@ -0,0 +1 @@
1
+__pycache__

+ 152
- 0
scripts/locinst.py View File

@@ -0,0 +1,152 @@
1
+#!/usr/bin/env python3
2
+
3
+import json
4
+import urllib.request
5
+import subprocess
6
+import os
7
+import sys
8
+import re
9
+
10
+LOCINST_DIR=os.environ['HOME']+'/.locinst'
11
+LOCINST_DB=os.environ['HOME']+'/.config/locinst'
12
+LOCINST_TMP='/tmp/locinst'
13
+
14
+DEBIAN_MIRROR = 'http://debian.polytech-lille.fr/debian/'
15
+
16
+def globallyInstalled(name):
17
+    try:
18
+        a = subprocess.check_output(['apt-cache', 'policy', 'name']).decode('utf8').strip().lower()
19
+        return 'Installed: (none)' not in [b.strip() for b in a.decode('utf8').split('\n')]
20
+    except FileNotFoundError:
21
+        return False
22
+
23
+def locallyInstalled(name):
24
+    return False
25
+
26
+def debian_install(name):
27
+    def findPackage(name):
28
+        raw = urllib.request.urlopen('http://sources.debian.net/api/search/' + name + '/')
29
+        data = json.loads(raw.read().decode('utf8'))
30
+        results = data['results']
31
+        if results['exact']:
32
+            return True
33
+        else:
34
+            print("Package " + name + " does not exist" + (", however you might want to try one of the following: " + ", ".join([pkg['name'] for pkg in results['other']]) if results['other'] else "") + ".")
35
+            return False
36
+        
37
+    def findVersion(name):
38
+        raw = urllib.request.urlopen('http://sources.debian.net/api/src/' + name + '/')
39
+        data = json.loads(raw.read().decode('utf8'))
40
+
41
+        def findByCodename(codename):
42
+            goodVersions = [version['version'] for version in data['versions'] if codename in version['suites']]
43
+            return goodVersions[0] if len(goodVersions) else False
44
+
45
+        try:
46
+            codename = subprocess.check_output(['lsb_release', '--codename', '--short']).decode('utf8').strip().lower()
47
+            choice = findByCodename(codename)
48
+            if choice:
49
+                return choice
50
+        except FileNotFoundError:
51
+            pass
52
+
53
+        return findByCodename('jessie')
54
+
55
+    def parseInfos(control):
56
+        paragraph = {}
57
+        key = ''
58
+
59
+        for line in control.strip().split('\n'):
60
+            if re.match('\s', line[0]):
61
+                try:
62
+                    paragraph[key] += '\n' + line.strip()
63
+                except KeyError:
64
+                    pass
65
+            elif re.match('^[\w-]+\:', line):
66
+                key = line.split(':')[0].lower()
67
+                paragraph[key] = line[len(key)+1:].strip()
68
+
69
+        return paragraph
70
+
71
+    def getArch():
72
+        arch = subprocess.check_output(['uname', '--machine']).decode('utf8').strip().lower()
73
+        if arch == 'x86_64':
74
+            arch = 'amd64'
75
+        return arch
76
+
77
+
78
+    def download(name, version):
79
+        arch = getArch()
80
+        filename =  name + '_' + version + '_' + arch
81
+
82
+        print("Downloading " + filename + "...")
83
+        url = DEBIAN_MIRROR + 'pool/main/' + (name[0] if name[0:3] != 'lib' else name[0:4]) + '/' + name + '/' + filename + '.deb'
84
+        debfile = LOCINST_TMP + '/' + filename + '.deb'
85
+        urllib.request.urlretrieve(url, debfile)
86
+
87
+        extractdir = LOCINST_TMP + '/' + filename
88
+        try:
89
+            os.mkdir(extractdir)
90
+        except FileExistsError:
91
+            pass
92
+        subprocess.check_call(['ar', 'x', debfile], cwd=extractdir)
93
+        subprocess.check_call(['rm', '-rf', debfile], stdout=subprocess.DEVNULL) 
94
+
95
+        controltar = [a for a in os.listdir(extractdir) if a.split('.')[:2] == ['control', 'tar']][0]
96
+        subprocess.check_call(['tar', 'xf', extractdir + '/' + controltar], cwd=extractdir)
97
+        with open(extractdir + '/control') as controlfile:
98
+            control = controlfile.read()
99
+
100
+        finaldir = LOCINST_TMP + '/' + name
101
+        try:
102
+            os.mkdir(finaldir)
103
+        except FileExistsError:
104
+            pass
105
+        datatar = [a for a in os.listdir(extractdir) if a.split('.')[:2] == ['data', 'tar']][0]
106
+        subprocess.check_call(['tar', 'xf', extractdir + '/' + datatar], cwd=finaldir)
107
+
108
+        subprocess.check_call(['rm', '-rf', extractdir]) 
109
+        return {
110
+                'final': finaldir,
111
+                'control': control
112
+        }
113
+
114
+
115
+    if not findPackage(name):
116
+        return 4
117
+
118
+    if globallyInstalled(name):
119
+        return 5
120
+
121
+    print("Installing " + name + "...")
122
+    version = findVersion(name)
123
+
124
+    if not version:
125
+        return 6
126
+
127
+    d = download(name, version)
128
+    finaldir, control = d['final'], d['control']
129
+
130
+    infos = parseInfos(control)
131
+
132
+    if 'depends' in infos:
133
+        for dep in infos['depends'].split(', '):
134
+            dep = dep.strip().split(' ')[0]
135
+            if not globallyInstalled(dep):
136
+                # print("Installing " + dep + " as a dependency")
137
+                # debian_install(dep)
138
+
139
+                # TODO For compatibility until locinst.sh is rewritten
140
+                try:
141
+                    subprocess.check_call([os.environ['HOME'] + '/.scripts/locinst.sh', 'debian', dep])
142
+                except subprocess.CalledProcessError:
143
+                    pass
144
+            
145
+    if 'recommends' in infos:
146
+        for rec in infos['recommends'].split(','):
147
+            print(name + " suggests you to install: " + rec.strip())
148
+
149
+    return 0
150
+
151
+# TODO For compatibility until locinst.sh is rewritten
152
+exit(debian_install(sys.argv[1]))

+ 11
- 2
scripts/locinst.sh View File

@@ -156,8 +156,12 @@ function locinst { # action package [other_info]*
156 156
 			locinst_pypi $dest $package $*
157 157
 			code=$?
158 158
 			;;
159
+		"debian")
160
+			$HOME/.scripts/locinst.py $package $*
161
+			code=$?
162
+			;;
159 163
 		*)
160
-			error "I don't know what to do. And don't beg for help with the commands."
164
+			#error "I don't know what to do. And don't beg for help with the commands."
161 165
 			return 1
162 166
 			;;
163 167
 	esac
@@ -182,6 +186,9 @@ function locinst { # action package [other_info]*
182 186
 		5)
183 187
 			error "Package already installed on system!"
184 188
 			;;
189
+		6)
190
+			error "Could not satisfy version requirements!"
191
+			;;
185 192
 		*)
186 193
 			error "Ugh... Something bad happened"
187 194
 	esac
@@ -191,4 +198,6 @@ function locinst { # action package [other_info]*
191 198
 
192 199
 }
193 200
 
194
-#
201
+if [ -n $1 ]; then
202
+    locinst $@
203
+fi

Loading…
Cancel
Save