source: trunk/GSASIIpath.py @ 1556

Last change on this file since 1556 was 1556, checked in by toby, 9 years ago

add trust opt to svn update

  • Property svn:eol-style set to native
  • Property svn:keywords set to Date Author Revision URL Id
File size: 11.8 KB
Line 
1# -*- coding: utf-8 -*-
2'''
3*GSASIIpath: locations & updates*
4---------------------------------
5
6Routines for dealing with file locations, etc.
7
8Determines the location of the compiled (.pyd or .so) libraries.
9
10Interfaces with subversion (svn):
11Determine the subversion release number by determining the highest version number
12where :func:`SetVersionNumber` is called (best done in every GSASII file).
13Other routines will update GSASII from the subversion server if svn can be
14found.
15'''
16
17import os
18import sys
19import platform
20# determine a binary path for the pyd files based on the host OS and the python version, 
21# path is relative to location of the script that is called as well as this file
22# this must be imported before anything that imports any .pyd/.so file for GSASII
23bindir = None
24if sys.platform == "win32":
25    if platform.architecture()[0] == '64bit':
26        bindir = 'binwin64-%d.%d' % sys.version_info[0:2]
27    else:
28        bindir = 'binwin%d.%d' % sys.version_info[0:2]
29elif sys.platform == "darwin":
30    import platform
31    if platform.architecture()[0] == '64bit':
32        bindir = 'binmac64-%d.%d' % sys.version_info[0:2]
33    else:
34        bindir = 'binmac%d.%d' % sys.version_info[0:2]
35    if platform.mac_ver()[0].startswith('10.5.'):
36        bindir += '_10.5'
37elif sys.platform == "linux2":
38    if platform.architecture()[0] == '64bit':
39        bindir = 'binlinux64-%d.%d' % sys.version_info[0:2]
40    else:
41        bindir = 'binlinux%d.%d' % sys.version_info[0:2]
42for loc in sys.path[0],os.path.abspath(os.path.split(__file__)[0]):
43    if bindir:
44        if os.path.exists(os.path.join(loc,bindir)) and os.path.join(loc,bindir) not in sys.path: 
45            sys.path.insert(0,os.path.join(loc,bindir))
46        # is there a bin directory? (created by a local compile), if so put
47        # that at the top of the path
48    if os.path.exists(os.path.join(loc,'bin')) and os.path.getsize(os.path.join(loc,'bin')):
49        bindir = 'bin'
50        if os.path.join(loc,'bin') not in sys.path: 
51            sys.path.insert(0,os.path.join(loc,bindir))
52print 'GSAS-II binary directory: ',os.path.join(loc,bindir)
53if bindir == None:
54    raise Exception,"**** ERROR GSAS-II binary libraries not found, GSAS-II fails ****"
55# add the data import and export directory to the search path
56path2GSAS2 = os.path.dirname(os.path.realpath(__file__)) # location of this file; save before any changes in pwd
57newpath = os.path.join(path2GSAS2,'imports')
58if newpath not in sys.path: sys.path.append(newpath)
59newpath = os.path.join(path2GSAS2,'exports')
60if newpath not in sys.path: sys.path.append(newpath)
61
62# setup read of config.py, if present
63try:
64    import config
65    configDict = config.__dict__
66    import inspect
67    vals = [True for i in inspect.getmembers(config) if '__' not in i[0]]
68    print str(len(vals))+' values read from config file '+os.path.abspath(config.__file__)
69except ImportError:
70    configDict = {}
71   
72def GetConfigValue(key,default=None):
73    '''Return the configuration file value for key or a default value if not present
74   
75    :param str key: a value to be found in the configuration (config.py) file
76    :param default: a value to be supplied is none is in the config file or
77      the config file is not found. Defaults to None
78    :returns: the value found or the default.
79    '''
80    return configDict.get(key,default)
81
82# routines for looking a version numbers in files
83version = -1
84def SetVersionNumber(RevString):
85    '''Set the subversion version number
86
87    :param str RevString: something like "$Revision: 1556 $"
88      that is set by subversion when the file is retrieved from subversion.
89
90    Place ``GSASIIpath.SetVersionNumber("$Revision: 1556 $")`` in every python
91    file.
92    '''
93    try:
94        RevVersion = int(RevString.split(':')[1].split()[0])
95        global version
96        version = max(version,RevVersion)
97    except:
98        pass
99       
100def GetVersionNumber():
101    '''Return the maximum version number seen in :func:`SetVersionNumber`
102    '''
103    return version
104
105def LoadConfigFile(filename):
106    '''Read a GSAS-II configuration file.
107    Comments (starting with "%") are removed, as are empty lines
108   
109    :param str filename: base file name (such as 'file.dat'). Files with this name
110      are located from the path and the contents of each are concatenated.
111    :returns: a list containing each non-empty (after removal of comments) line
112      found in every matching config file.
113    '''
114    info = []
115    for path in sys.path:
116        fil = os.path.join(path,filename)
117        if not os.path.exists(fil): continue
118        try:
119            i = 0
120            fp = open(fil,'r')
121            for line in fp:
122                expr = line.split('#')[0].strip()
123                if expr:
124                    info.append(expr)
125                    i += 1
126            print(str(i)+' lines read from config file '+fil)
127        finally:
128            fp.close()
129    return info
130
131
132# routines to interface with subversion
133def whichsvn():
134    '''Returns a path to the subversion exe file, if any is found.
135    Searches the current path as well as subdirectory "svn" and
136    "svn/bin" in the location of the GSASII source files.
137
138    :returns: None if svn is not found or an absolute path to the subversion
139      executable file.
140    '''
141    def is_exe(fpath):
142        return os.path.isfile(fpath) and os.access(fpath, os.X_OK)
143    svnprog = 'svn'
144    if sys.platform == "win32": svnprog += '.exe'
145    pathlist = os.environ["PATH"].split(os.pathsep)
146    pathlist.insert(0,os.path.join(os.path.split(__file__)[0],'svn'))
147    pathlist.insert(1,os.path.join(os.path.split(__file__)[0],'svn','bin'))
148    for path in pathlist:
149        exe_file = os.path.join(path, svnprog)
150        if is_exe(exe_file):
151            return os.path.abspath(exe_file)
152
153def svnGetLog(fpath=os.path.split(__file__)[0],version=None):
154    '''Get the revision log information for a specific version of the
155
156    :param str fpath: path to repository dictionary, defaults to directory where
157       the current file is located.
158    :param int version: the version number to be looked up or None (default)
159       for the latest version.
160
161    :returns: a dictionary with keys (one hopes) 'author', 'date', 'msg', and 'revision'
162
163    '''
164    import subprocess
165    import xml.etree.ElementTree as ET
166    svn = whichsvn()
167    if not svn: return
168    if version is not None:
169        vstr = '-r'+str(version)
170    else:
171        vstr = '-rHEAD'
172
173    cmd = [svn,'log',fpath,'--xml',vstr]
174    s = subprocess.Popen(cmd,
175                         stdout=subprocess.PIPE,stderr=subprocess.PIPE)
176    out,err = s.communicate()
177    if err:
178        print 'out=',out
179        print 'err=',err
180        return None
181    x = ET.fromstring(out)
182    d = {}
183    for i in x.iter('logentry'):
184        d = {'revision':i.attrib.get('revision','?')}
185        for j in i:
186            d[j.tag] = j.text
187        break # only need the first
188    return d
189
190def svnGetRev(fpath=os.path.split(__file__)[0],local=True):
191    '''Obtain the version number for the either the last update of the local version
192    or contacts the subversion server to get the latest update version (# of Head).
193
194    :param str fpath: path to repository dictionary, defaults to directory where
195       the current file is located
196    :param bool local: determines the type of version number, where
197       True (default): returns the latest installed update
198       False: returns the version number of Head on the server
199
200    :Returns: the version number as an str or
201       None if there is a subversion error (likely because the path is
202       not a repository or svn is not found)
203    '''
204
205    import subprocess
206    import xml.etree.ElementTree as ET
207    svn = whichsvn()
208    if not svn: return
209    if local:
210        cmd = [svn,'info',fpath,'--xml']
211    else:
212        cmd = [svn,'info',fpath,'--xml','-rHEAD']
213    s = subprocess.Popen(cmd+['--non-interactive', '--trust-server-cert'],
214                         stdout=subprocess.PIPE,stderr=subprocess.PIPE)
215    out,err = s.communicate()
216    if err:
217        print 'svn failed, retry w/o --trust...\nout=',out
218        print 'err=',err
219        s = subprocess.Popen(cmd,
220                            stdout=subprocess.PIPE,stderr=subprocess.PIPE)
221        out,err = s.communicate()
222        if err:
223            print 'out=',out
224            print 'err=',err
225            return None
226    x = ET.fromstring(out)
227    for i in x.iter('entry'):
228        rev = i.attrib.get('revision')
229        if rev: return rev
230
231def svnFindLocalChanges(fpath=os.path.split(__file__)[0]):
232    '''Returns a list of files that were changed locally. If no files are changed,
233       the list has length 0
234
235    :param fpath: path to repository dictionary, defaults to directory where
236       the current file is located
237
238    :returns: None if there is a subversion error (likely because the path is
239       not a repository or svn is not found)
240
241    '''
242    import subprocess
243    import xml.etree.ElementTree as ET
244    svn = whichsvn()
245    if not svn: return
246    cmd = [svn,'status',fpath,'--xml']
247    s = subprocess.Popen(cmd,
248                         stdout=subprocess.PIPE,stderr=subprocess.PIPE)
249    out,err = s.communicate()
250    if err: return None
251    x = ET.fromstring(out)
252    changed = []
253    for i in x.iter('entry'):
254        if i.find('wc-status').attrib.get('item') == 'modified': 
255            changed.append(i.attrib.get('path'))
256    return changed
257
258def svnUpdateDir(fpath=os.path.split(__file__)[0],version=None):
259    '''This performs an update of the files in a local directory from a server.
260
261    :param str fpath: path to repository dictionary, defaults to directory where
262       the current file is located
263    :param version: the number of the version to be loaded. Used only
264       cast as a string, but should be an integer or something that corresponds to a
265       string representation of an integer value when cast. A value of None (default)
266       causes the latest version on the server to be used.
267    '''
268    import subprocess
269    svn = whichsvn()
270    if not svn: return
271    if version:
272        verstr = '-r' + str(version)
273    else:
274        verstr = '-rHEAD'
275    cmd = [svn,'update',fpath,verstr,
276           '--non-interactive',
277           '--accept','theirs-conflict','--force']
278    s = subprocess.Popen(cmd+'['--trust-server-cert'],
279                         stdout=subprocess.PIPE,stderr=subprocess.PIPE)
280    out,err = s.communicate()
281    print out
282    if err:
283        s = subprocess.Popen(cmd,
284                         stdout=subprocess.PIPE,stderr=subprocess.PIPE)
285        out,err = s.communicate()
286        if err:
287            print(60*"=")
288            print ("****** An error was noted, see below *********")
289            print(60*"=")
290            print err
291            sys.exit()
292
293def svnUpdateProcess(version=None,projectfile=None):
294    '''perform an update of GSAS-II in a separate python process'''
295    import subprocess
296    if not projectfile:
297        projectfile = ''
298    else:
299        projectfile = os.path.realpath(projectfile)
300        print 'restart using',projectfile
301    if not version:
302        version = ''
303    else:
304        version = str(version)
305    # start the upgrade in a separate interpreter (avoids loading .pyd files)
306    subprocess.Popen([sys.executable,__file__,projectfile,version])
307    sys.exit()
308
309if __name__ == '__main__':
310    import subprocess
311    import time
312    time.sleep(1) # delay to give the main process a chance to exit
313    # perform an update and restart GSAS-II
314    project,version = sys.argv[1:3]
315    loc = os.path.dirname(__file__)
316    if version:
317        print("Regress to version "+str(version))
318        svnUpdateDir(loc,version=version)
319    else:
320        print("Update to current version")
321        svnUpdateDir(loc)
322    if project:
323        print("Restart GSAS-II with project file "+str(project))
324        subprocess.Popen([sys.executable,os.path.join(loc,'GSASII.py'),project])
325    else:
326        print("Restart GSAS-II without a project file ")
327        subprocess.Popen([sys.executable,os.path.join(loc,'GSASII.py')])
328    print 'exiting update process'
329    sys.exit()
330   
Note: See TracBrowser for help on using the repository browser.