chiark / gitweb /
Remove a bunch of unused imports
[fdroidserver.git] / fdroidserver / import.py
1 #!/usr/bin/env python
2 # -*- coding: utf-8 -*-
3 #
4 # import.py - part of the FDroid server tools
5 # Copyright (C) 2010-12, Ciaran Gultnieks, ciaran@ciarang.com
6 #
7 # This program is free software: you can redistribute it and/or modify
8 # it under the terms of the GNU Affero General Public License as published by
9 # the Free Software Foundation, either version 3 of the License, or
10 # (at your option) any later version.
11 #
12 # This program is distributed in the hope that it will be useful,
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 # GNU Affero General Public License for more details.
16 #
17 # You should have received a copy of the GNU Affero General Public License
18 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
19
20 import sys
21 import os
22 import shutil
23 import urllib
24 from optparse import OptionParser
25
26
27 # Get the repo type and address from the given web page. The page is scanned
28 # in a rather naive manner for 'git clone xxxx', 'hg clone xxxx', etc, and
29 # when one of these is found it's assumed that's the information we want.
30 # Returns repotype, address, or None, reason
31 def getrepofrompage(url):
32
33     req = urllib.urlopen(url)
34     if req.getcode() != 200:
35         return (None, 'Unable to find source at ' + sourcecode + ' - return code ' + str(req.getcode()))
36     page = req.read()
37
38     # Works for Google Code and BitBucket...
39     index = page.find('hg clone')
40     if index != -1:
41         repotype = 'hg'
42         repo = page[index + 9:]
43         index = repo.find('<')
44         if index == -1:
45             return (None, "Error while getting repo address")
46         repo = repo[:index]
47         return (repotype, repo)
48
49     # Works for Google Code and BitBucket...
50     index=page.find('git clone')
51     if index != -1:
52         repotype = 'git'
53         repo = page[index + 10:]
54         index = repo.find('<')
55         if index == -1:
56             return (None, "Error while getting repo address")
57         repo = repo[:index]
58         return (repotype, repo)
59
60     # Google Code only...
61     index=page.find('svn checkout')
62     if index != -1:
63         repotype = 'git-svn'
64         repo = page[index + 13:]
65         prefix = '<strong><em>http</em></strong>'
66         if not repo.startswith(prefix):
67             return (None, "Unexpected checkout instructions format")
68         repo = 'http' + repo[len(prefix):]
69         index = repo.find('<')
70         if index == -1:
71             return (None, "Error while getting repo address - no end tag? '" + repo + "'")
72             sys.exit(1)
73         repo = repo[:index]
74         index = repo.find(' ')
75         if index == -1:
76             return (None, "Error while getting repo address - no space? '" + repo + "'")
77         repo = repo[:index]
78         return (repotype, repo)
79
80     return (None, "No information found." + page)
81
82
83 def main():
84
85     # Read configuration...
86     execfile('config.py', globals())
87
88     import common
89
90     # Parse command line...
91     parser = OptionParser()
92     parser.add_option("-u", "--url", default=None,
93                       help="Project URL to import from.")
94     parser.add_option("-s", "--subdir", default=None,
95                       help="Path to main android project subdirectory, if not in root.")
96     parser.add_option("-r", "--repo", default=None,
97                       help="Allows a different repo to be specified for a multi-repo google code project")
98     (options, args) = parser.parse_args()
99
100     if not options.url:
101         print "Specify project url."
102         sys.exit(1)
103     url = options.url
104
105     tmp_dir = 'tmp'
106     if not os.path.isdir(tmp_dir):
107         print "Creating temporary directory"
108         os.makedirs(tmp_dir)
109
110     # Get all apps...
111     apps = common.read_metadata()
112
113     # Figure out what kind of project it is...
114     projecttype = None
115     issuetracker = None
116     license = None
117     website = url #by default, we might override it
118     if url.startswith('git://'):
119         projecttype = 'git'
120         repo = url
121         repotype = 'git'
122         sourcecode = ""
123         website = ""
124     elif url.startswith('https://github.com'):
125         if url.endswith('/'):
126             url = url[:-1]
127         if url.endswith('.git'):
128             print "A github URL should point to the project, not the git repo"
129             sys.exit(1)
130         projecttype = 'github'
131         repo = url + '.git'
132         repotype = 'git'
133         sourcecode = url
134     elif url.startswith('https://gitorious.org/'):
135         projecttype = 'gitorious'
136         repo = 'https://git.gitorious.org/' + url[22:] + '.git'
137         repotype = 'git'
138         sourcecode = url
139     elif url.startswith('https://bitbucket.org/'):
140         if url.endswith('/'):
141             url = url[:-1]
142         projecttype = 'bitbucket'
143         sourcecode = url + '/src'
144         issuetracker = url + '/issues'
145         # Figure out the repo type and adddress...
146         repotype, repo = getrepofrompage(sourcecode)
147         if not repotype:
148             print "Unable to determine vcs type. " + repo
149             sys.exit(1)
150     elif url.startswith('http://code.google.com/p/'):
151         if not url.endswith('/'):
152             url += '/';
153         projecttype = 'googlecode'
154         sourcecode = url + 'source/checkout'
155         if options.repo:
156             sourcecode += "?repo=" + options.repo
157         issuetracker = url + 'issues/list'
158
159         # Figure out the repo type and adddress...
160         repotype, repo = getrepofrompage(sourcecode)
161         if not repotype:
162             print "Unable to determine vcs type. " + repo
163             sys.exit(1)
164
165         # Figure out the license...
166         req = urllib.urlopen(url)
167         if req.getcode() != 200:
168             print 'Unable to find project page at ' + sourcecode + ' - return code ' + str(req.getcode())
169             sys.exit(1)
170         page = req.read()
171         index = page.find('Code license')
172         if index == -1:
173             print "Couldn't find license data"
174             sys.exit(1)
175         ltext = page[index:]
176         lprefix = 'rel="nofollow">'
177         index = ltext.find(lprefix)
178         if index == -1:
179             print "Couldn't find license text"
180             sys.exit(1)
181         ltext = ltext[index + len(lprefix):]
182         index = ltext.find('<')
183         if index == -1:
184             print "License text not formatted as expected"
185             sys.exit(1)
186         ltext = ltext[:index]
187         if ltext == 'GNU GPL v3':
188             license = 'GPLv3'
189         elif ltext == 'GNU GPL v2':
190             license = 'GPLv2'
191         elif ltext == 'Apache License 2.0':
192             license = 'Apache2'
193         elif ltext == 'MIT License':
194             license = 'MIT'
195         elif ltext == 'GNU Lesser GPL':
196             license = 'LGPL'
197         elif ltext == 'Mozilla Public License 1.1':
198             license = 'MPL'
199         elif ltext == 'New BSD License':
200             license = 'NewBSD'
201         else:
202             print "License " + ltext + " is not recognised"
203             sys.exit(1)
204
205     if not projecttype:
206         print "Unable to determine the project type."
207         print "The URL you supplied was not in one of the supported formats. Please consult"
208         print "the manual for a list of supported formats, and supply one of those."
209         sys.exit(1)
210
211     # Get a copy of the source so we can extract some info...
212     print 'Getting source from ' + repotype + ' repo at ' + repo
213     src_dir = os.path.join(tmp_dir, 'importer')
214     if os.path.exists(src_dir):
215         shutil.rmtree(src_dir)
216     vcs = common.getvcs(repotype, repo, src_dir, sdk_path)
217     vcs.gotorevision(None)
218     if options.subdir:
219         root_dir = os.path.join(src_dir, options.subdir)
220     else:
221         root_dir = src_dir
222
223     # Check AndroidManiifest.xml exists...
224     if not os.path.exists(root_dir + '/AndroidManifest.xml'):
225         print "AndroidManifest.xml did not exist in the expected location. Specify --subdir?"
226         sys.exit(1)
227
228     # Extract some information...
229     paths = common.manifest_paths(root_dir, None)
230     version, vercode, package = common.parse_androidmanifests(paths)
231     if not package:
232         print "Couldn't find package ID"
233         sys.exit(1)
234     if not version:
235         print "Couldn't find latest version name"
236         sys.exit(1)
237     if not vercode:
238         print "Couldn't find latest version code"
239         sys.exit(1)
240
241     # Make sure it's actually new...
242     for app in apps:
243         if app['id'] == package:
244             print "Package " + package + " already exists"
245             sys.exit(1)
246
247     # Construct the metadata...
248     app = common.parse_metadata(None)
249     app['id'] = package
250     app['Web Site'] = website
251     app['Source Code'] = sourcecode
252     if issuetracker:
253         app['Issue Tracker'] = issuetracker
254     if license:
255         app['License'] = license
256     app['Repo Type'] = repotype
257     app['Repo'] = repo
258
259     # Create a build line...
260     build = {}
261     build['version'] = version
262     build['vercode'] = vercode
263     build['commit'] = '?'
264     if options.subdir:
265         build['subdir'] = options.subdir
266     if os.path.exists(os.path.join(root_dir, 'jni')):
267         build['buildjni'] = 'yes'
268     app['builds'].append(build)
269     app['comments'].append(('build:' + version,
270         "#Generated by import.py - check this is the right version, and find the right commit!"))
271
272     # Keep the repo directory to save bandwidth...
273     if not os.path.exists('build'):
274         os.mkdir('build')
275     shutil.move(src_dir, os.path.join('build', package))
276     with open('build/.fdroidvcs-' + package, 'w') as f:
277         f.write(repotype + ' ' + repo)
278
279     metafile = os.path.join('metadata', package + '.txt')
280     common.write_metadata(metafile, app)
281     print "Wrote " + metafile
282
283
284 if __name__ == "__main__":
285     main()
286