Merge release-0.28.17 from 'tools/mic'
[platform/upstream/mic.git] / mic / utils / grabber.py
1 #!/usr/bin/python
2
3 # Copyright (c) 2014 Intel, Inc.
4 #
5 # This program is free software; you can redistribute it and/or modify it
6 # under the terms of the GNU General Public License as published by the Free
7 # Software Foundation; version 2 of the License
8 #
9 # This program is distributed in the hope that it will be useful, but
10 # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
11 # or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12 # for more details.
13 #
14 # You should have received a copy of the GNU General Public License along
15 # with this program; if not, write to the Free Software Foundation, Inc., 59
16 # Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17
18 import os
19 import sys
20 import fcntl
21 import struct
22 import termios
23
24 from mic import msger
25 from mic.utils import runner
26 from mic.utils.errors import CreatorError
27 from mic.utils.safeurl import SafeURL
28
29 from urlgrabber import grabber
30 from urlgrabber import __version__ as grabber_version
31
32 def myurlgrab(url, filename, proxies, progress_obj = None):
33     g = grabber.URLGrabber()
34     if progress_obj is None:
35         progress_obj = TextProgress()
36
37     if url.startswith("file:/"):
38         filepath = "/%s" % url.replace("file:", "").lstrip('/')
39         if not os.path.exists(filepath):
40             raise CreatorError("URLGrabber error: can't find file %s" % url)
41         if url.endswith('.rpm'):
42             return filepath
43         else:
44             # untouch repometadata in source path
45             runner.show(['cp', '-f', filepath, filename])
46
47     else:
48         try:
49             # cast url to str here, sometimes it can be unicode,
50             # but pycurl only accept str
51             filename = g.urlgrab(url=str(url),
52                                  filename=filename,
53                                  ssl_verify_host=False,
54                                  ssl_verify_peer=False,
55                                  proxies=proxies,
56                                  http_headers=(('Pragma', 'no-cache'),),
57                                  quote=0,
58                                  progress_obj=progress_obj)
59         except grabber.URLGrabError as err:
60             tmp = SafeURL(url)
61             msg = str(err)
62
63             if msg.find(url) < 0:
64                 msg += ' on %s' % tmp
65             else:
66                 msg = msg.replace(url, tmp)
67
68             raise CreatorError(msg)
69
70     return filename
71
72 def terminal_width(fd=1):
73     """ Get the real terminal width """
74     try:
75         buf = 'abcdefgh'
76         buf = fcntl.ioctl(fd, termios.TIOCGWINSZ, buf)
77         return struct.unpack('hhhh', buf)[1]
78     except: # IOError
79         return 80
80
81 def truncate_url(url, width):
82     return os.path.basename(url)[0:width]
83
84 class TextProgress(object):
85     # make the class as singleton
86     _instance = None
87     def __new__(cls, *args, **kwargs):
88         if not cls._instance:
89             cls._instance = super(TextProgress, cls).__new__(cls, *args, **kwargs)
90
91         return cls._instance
92
93     def __init__(self, totalnum = None):
94         self.total = totalnum
95         self.counter = 1
96
97     def start(self, filename, url, *args, **kwargs):
98         self.url = url
99         self.termwidth = terminal_width()
100         if self.total is None:
101             msger.info("Retrieving %s ..." % truncate_url(self.url, self.termwidth - 15))
102         else:
103             msger.info("Retrieving %s [%d/%d] ..." % (truncate_url(self.url, self.termwidth - 25), self.counter, self.total))
104
105     def update(self, *args):
106         pass
107
108     def end(self, *args):
109         if self.counter == self.total:
110             msger.raw("\n")
111
112         if self.total is not None:
113             self.counter += 1
114