Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
C
converse.js
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
converse.js
Commits
ade62804
Commit
ade62804
authored
May 02, 2012
by
Michal Čihař
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Lock git repository while doing merge
parent
6fd2a8f1
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
115 additions
and
21 deletions
+115
-21
weblate/trans/filelock.py
weblate/trans/filelock.py
+77
-0
weblate/trans/models.py
weblate/trans/models.py
+38
-21
No files found.
weblate/trans/filelock.py
0 → 100644
View file @
ade62804
import
os
import
time
import
errno
class
FileLockException
(
Exception
):
pass
class
FileLock
(
object
):
""" A file locking mechanism that has context-manager support so
you can use it in a with statement. This should be relatively cross
compatible as it doesn't rely on msvcrt or fcntl for the locking.
"""
def
__init__
(
self
,
file_name
,
timeout
=
10
,
delay
=
.
05
):
""" Prepare the file locker. Specify the file to lock and optionally
the maximum timeout and the delay between each attempt to lock.
"""
self
.
is_locked
=
False
self
.
lockfile
=
os
.
path
.
join
(
os
.
getcwd
(),
"%s.lock"
%
file_name
)
self
.
file_name
=
file_name
self
.
timeout
=
timeout
self
.
delay
=
delay
def
acquire
(
self
):
""" Acquire the lock, if possible. If the lock is in use, it check again
every `wait` seconds. It does this until it either gets the lock or
exceeds `timeout` number of seconds, in which case it throws
an exception.
"""
start_time
=
time
.
time
()
while
True
:
try
:
self
.
fd
=
os
.
open
(
self
.
lockfile
,
os
.
O_CREAT
|
os
.
O_EXCL
|
os
.
O_RDWR
)
break
;
except
OSError
as
e
:
if
e
.
errno
!=
errno
.
EEXIST
:
raise
if
(
time
.
time
()
-
start_time
)
>=
self
.
timeout
:
raise
FileLockException
(
"Timeout occured."
)
time
.
sleep
(
self
.
delay
)
self
.
is_locked
=
True
def
release
(
self
):
""" Get rid of the lock by deleting the lockfile.
When working in a `with` statement, this gets automatically
called at the end.
"""
if
self
.
is_locked
:
os
.
close
(
self
.
fd
)
os
.
unlink
(
self
.
lockfile
)
self
.
is_locked
=
False
def
__enter__
(
self
):
""" Activated when used in the with statement.
Should automatically acquire a lock to be used in the with block.
"""
if
not
self
.
is_locked
:
self
.
acquire
()
return
self
def
__exit__
(
self
,
type
,
value
,
traceback
):
""" Activated at the end of the with statement.
It automatically releases the lock if it isn't locked.
"""
if
self
.
is_locked
:
self
.
release
()
def
__del__
(
self
):
""" Make sure that the FileLock instance doesn't leave a lockfile
lying around.
"""
self
.
release
()
weblate/trans/models.py
View file @
ade62804
...
...
@@ -24,6 +24,7 @@ import weblate
from
weblate.lang.models
import
Language
from
weblate.trans.checks
import
CHECKS
from
weblate.trans.managers
import
TranslationManager
,
UnitManager
,
DictionaryManager
from
weblate.trans.filelock
import
FileLock
from
util
import
is_plural
,
split_plural
,
join_plural
logger
=
logging
.
getLogger
(
'weblate'
)
...
...
@@ -233,6 +234,20 @@ class SubProject(models.Model):
'''
return
os
.
path
.
join
(
self
.
project
.
get_path
(),
self
.
slug
)
def
get_lock_path
(
self
):
'''
Returns full path to subproject git repository.
'''
return
os
.
path
.
join
(
self
.
project
.
get_path
(),
self
.
slug
+
'.lock'
)
def
get_lock
(
self
):
'''
Returns lock object for current translation instance.
'''
if
not
hasattr
(
self
,
'__lock__'
):
self
.
__lock__
=
FileLock
(
self
.
get_lock_path
())
return
self
.
__lock__
def
can_push
(
self
):
'''
Returns true if push is possible for this subproject.
...
...
@@ -387,27 +402,29 @@ class SubProject(models.Model):
# Update remote repo
self
.
pull_repo
(
False
,
gitrepo
)
try
:
# Try to merge it
gitrepo
.
git
.
merge
(
'origin/%s'
%
self
.
branch
)
logger
.
info
(
'merged remote into repo %s'
,
self
.
__unicode__
())
return
True
except
Exception
,
e
:
# In case merge has failer recover and tell admins
status
=
gitrepo
.
git
.
status
()
gitrepo
.
git
.
merge
(
'--abort'
)
logger
.
warning
(
'failed merge on repo %s'
,
self
.
__unicode__
())
msg
=
'Error:
\
n
%s'
%
str
(
e
)
msg
+=
'
\
n
\
n
Status:
\
n
'
+
status
mail_admins
(
'failed merge on repo %s'
%
self
.
__unicode__
(),
msg
)
if
request
is
not
None
:
messages
.
error
(
request
,
_
(
'Failed to merge remote branch into %s.'
)
%
self
.
__unicode__
())
return
False
finally
:
del
gitrepo
# Mege with lock acquired
with
self
.
get_lock
():
try
:
# Try to merge it
gitrepo
.
git
.
merge
(
'origin/%s'
%
self
.
branch
)
logger
.
info
(
'merged remote into repo %s'
,
self
.
__unicode__
())
return
True
except
Exception
,
e
:
# In case merge has failer recover and tell admins
status
=
gitrepo
.
git
.
status
()
gitrepo
.
git
.
merge
(
'--abort'
)
logger
.
warning
(
'failed merge on repo %s'
,
self
.
__unicode__
())
msg
=
'Error:
\
n
%s'
%
str
(
e
)
msg
+=
'
\
n
\
n
Status:
\
n
'
+
status
mail_admins
(
'failed merge on repo %s'
%
self
.
__unicode__
(),
msg
)
if
request
is
not
None
:
messages
.
error
(
request
,
_
(
'Failed to merge remote branch into %s.'
)
%
self
.
__unicode__
())
return
False
finally
:
del
gitrepo
def
get_mask_matches
(
self
):
'''
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment