1 # ***** BEGIN LICENSE BLOCK *****
2 # Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 # The contents of this file are subject to the Mozilla Public License Version
5 # 1.1 (the "License"); you may not use this file except in compliance with
6 # the License. You may obtain a copy of the License at
7 # http://www.mozilla.org/MPL/
9 # Software distributed under the License is distributed on an "AS IS" basis,
10 # WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11 # for the specific language governing rights and limitations under the
14 # The Original Code is Mozilla build system.
16 # The Initial Developer of the Original Code is
18 # Portions created by the Initial Developer are Copyright (C) 2008
19 # the Initial Developer. All Rights Reserved.
22 # Axel Hecht <axel@pike.org>
24 # Alternatively, the contents of this file may be used under the terms of
25 # either the GNU General Public License Version 2 or later (the "GPL"), or
26 # the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27 # in which case the provisions of the GPL or the LGPL are applicable instead
28 # of those above. If you wish to allow use of your version of this file only
29 # under the terms of either the GPL or the LGPL, and not to allow others to
30 # use your version of this file under the terms of the MPL, indicate your
31 # decision by deleting the provisions above and replace them with the notice
32 # and other provisions required by the GPL or the LGPL. If you do not delete
33 # the provisions above, a recipient may use your version of this file under
34 # the terms of any one of the MPL, the GPL or the LGPL.
36 # ***** END LICENSE BLOCK *****
38 '''Utility methods to be used by python build infrastructure.
47 class LockFile(object):
48 '''LockFile is used by the lockFile method to hold the lock.
50 This object should not be used directly, but only through
51 the lockFile method below.
53 def __init__(self
, lockfile
):
54 self
.lockfile
= lockfile
56 os
.remove(self
.lockfile
)
59 def lockFile(lockfile
, max_wait
= 600):
60 '''Create and hold a lockfile of the given name, with the given timeout.
62 To release the lock, delete the returned object.
66 fd
= os
.open(lockfile
, os
.O_EXCL | os
.O_RDWR | os
.O_CREAT
)
67 # we created the lockfile, so we're the owner
70 if e
.errno
!= errno
.EEXIST
:
75 # the lock file exists, try to stat it to get its age
76 # and read its contents to report the owner PID
77 f
= open(lockfile
, "r")
80 if e
.errno
!= errno
.ENOENT
:
81 sys
.exit("%s exists but stat() failed: %s" %
82 (lockfile
, e
.strerror
))
83 # we didn't create the lockfile, so it did exist, but it's
84 # gone now. Just try again
87 # we didn't create the lockfile and it's still there, check
89 now
= int(time
.time())
90 if now
- s
[stat
.ST_MTIME
] > max_wait
:
92 sys
.exit("%s has been locked for more than " \
93 "%d seconds (PID %s)" % (lockfile
, max_wait
,
96 # it's not been locked too long, wait a while and retry
100 # if we get here. we have the lockfile. Convert the os.open file
101 # descriptor into a Python file object and record our PID in it
103 f
= os
.fdopen(fd
, "w")
104 f
.write("%d\n" % os
.getpid())
106 return LockFile(lockfile
)
108 class pushback_iter(object):
109 '''Utility iterator that can deal with pushed back elements.
111 This behaves like a regular iterable, just that you can call
113 to get the givem item as next item in the iteration.
115 def __init__(self
, iterable
):
116 self
.it
= iter(iterable
)
117 self
.pushed_back
= []
122 def __nonzero__(self
):
127 self
.pushed_back
.insert(0, self
.it
.next())
128 except StopIteration:
135 return self
.pushed_back
.pop()
136 return self
.it
.next()
138 def pushback(self
, item
):
139 self
.pushed_back
.append(item
)