##// END OF EJS Templates
merge with brendan
Benoit Boissinot -
r3076:1a792e4a merge default
parent child Browse files
Show More
@@ -0,0 +1,34 b''
1 #!/bin/sh
2 #
3 # test for branch handling
4 #
5 # XXX: need more tests
6
7 hg init
8 echo a > a
9 echo b > b
10 hg ci -A -m 0 -d "1000000 0"
11 echo aa > a
12 echo bb > b
13 hg ci -m 1 -d "1000000 0"
14 hg tag -l foo
15 hg update 0
16 hg parents -b
17
18 # test update
19 hg update -b foo
20 hg parents
21
22 # test merge
23 hg update 0
24 echo c > c
25 hg ci -A -m 0.0 -d "1000000 0"
26 hg merge -b foo
27 hg parents -b
28
29 # re-test with more branches
30 hg update -C 0
31 echo d > d
32 hg ci -A -m 0.0 -d "1000000 0"
33 hg merge -b foo
34 hg parents -b
@@ -0,0 +1,55 b''
1 adding a
2 adding b
3 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
4 changeset: 0:b544c4ac4389
5 user: test
6 date: Mon Jan 12 13:46:40 1970 +0000
7 summary: 0
8
9 Using head f4ac749470f2 for branch foo
10 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
11 changeset: 1:f4ac749470f2
12 tag: foo
13 tag: tip
14 user: test
15 date: Mon Jan 12 13:46:40 1970 +0000
16 summary: 1
17
18 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
19 adding c
20 Using head f4ac749470f2 for branch foo
21 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
22 (branch merge, don't forget to commit)
23 changeset: 2:1505d56ee00e
24 tag: tip
25 parent: 0:b544c4ac4389
26 user: test
27 date: Mon Jan 12 13:46:40 1970 +0000
28 summary: 0.0
29
30 changeset: 1:f4ac749470f2
31 tag: foo
32 branch: foo
33 user: test
34 date: Mon Jan 12 13:46:40 1970 +0000
35 summary: 1
36
37 2 files updated, 0 files merged, 1 files removed, 0 files unresolved
38 adding d
39 Using head f4ac749470f2 for branch foo
40 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
41 (branch merge, don't forget to commit)
42 changeset: 3:53b72df12ae5
43 tag: tip
44 parent: 0:b544c4ac4389
45 user: test
46 date: Mon Jan 12 13:46:40 1970 +0000
47 summary: 0.0
48
49 changeset: 1:f4ac749470f2
50 tag: foo
51 branch: foo
52 user: test
53 date: Mon Jan 12 13:46:40 1970 +0000
54 summary: 1
55
@@ -105,8 +105,7 b' def dodiff(ui, repo, diffcmd, diffopts, '
105 else:
105 else:
106 dir2 = snapshot_wdir(modified + added)
106 dir2 = snapshot_wdir(modified + added)
107 cmdline = ('%s %s %s %s' %
107 cmdline = ('%s %s %s %s' %
108 (util.shellquote(diffcmd),
108 (util.shellquote(diffcmd), ' '.join(diffopts),
109 ' '.join(map(util.shellquote, diffopts)),
110 util.shellquote(dir1), util.shellquote(dir2)))
109 util.shellquote(dir1), util.shellquote(dir2)))
111 ui.debug('running %r in %s\n' % (cmdline, tmproot))
110 ui.debug('running %r in %s\n' % (cmdline, tmproot))
112 util.system(cmdline, cwd=tmproot)
111 util.system(cmdline, cwd=tmproot)
@@ -7,68 +7,7 b''
7
7
8 from mercurial.demandload import *
8 from mercurial.demandload import *
9 demandload(globals(), 'time sys signal os')
9 demandload(globals(), 'time sys signal os')
10 demandload(globals(), 'mercurial:hg,mdiff,fancyopts,commands,ui,util')
10 demandload(globals(), 'mercurial:hg,fancyopts,commands,ui,util,patch')
11
12 def filterfiles(files, filters):
13 l = [x for x in filters if x in files]
14
15 for t in files:
16 if not t.endswith("/"):
17 t += "/"
18 l += [x for x in filters if x.startswith(t)]
19 return l
20
21 def dodiff(fp, ui, repo, node1, node2, files=None, match=util.always,
22 changes=None, text=False):
23 def date(c):
24 return time.asctime(time.gmtime(c[2][0]))
25
26 if not changes:
27 changes = repo.status(node1, node2, files, match=match)[:5]
28 modified, added, removed, deleted, unknown = changes
29 if files:
30 modified, added, removed = map(lambda x: filterfiles(files, x),
31 (modified, added, removed))
32
33 if not modified and not added and not removed:
34 return
35
36 if node2:
37 change = repo.changelog.read(node2)
38 mmap2 = repo.manifest.read(change[0])
39 date2 = date(change)
40 def read(f):
41 return repo.file(f).read(mmap2[f])
42 else:
43 date2 = time.asctime()
44 if not node1:
45 node1 = repo.dirstate.parents()[0]
46 def read(f):
47 return repo.wfile(f).read()
48
49 change = repo.changelog.read(node1)
50 mmap = repo.manifest.read(change[0])
51 date1 = date(change)
52
53 opts = mdiff.diffopts()
54 opts.text = text
55 for f in modified:
56 to = None
57 if f in mmap:
58 to = repo.file(f).read(mmap[f])
59 tn = read(f)
60 fp.write("diff --git a/%s b/%s\n" % (f, f))
61 fp.write(mdiff.unidiff(to, date1, tn, date2, f, None, opts=opts))
62 for f in added:
63 to = None
64 tn = read(f)
65 fp.write("diff --git /dev/null b/%s\n" % (f))
66 fp.write(mdiff.unidiff(to, date1, tn, date2, f, None, opts=opts))
67 for f in removed:
68 to = repo.file(f).read(mmap[f])
69 tn = None
70 fp.write("diff --git a/%s /dev/null\n" % (f))
71 fp.write(mdiff.unidiff(to, date1, tn, date2, f, None, opts=opts))
72
11
73 def difftree(ui, repo, node1=None, node2=None, *files, **opts):
12 def difftree(ui, repo, node1=None, node2=None, *files, **opts):
74 """diff trees from two commits"""
13 """diff trees from two commits"""
@@ -86,7 +25,7 b' def difftree(ui, repo, node1=None, node2'
86
25
87 change = repo.changelog.read(node1)
26 change = repo.changelog.read(node1)
88 mmap = repo.manifest.read(change[0])
27 mmap = repo.manifest.read(change[0])
89 empty = "0" * 40;
28 empty = hg.short(hg.nullid)
90
29
91 for f in modified:
30 for f in modified:
92 # TODO get file permissions
31 # TODO get file permissions
@@ -123,7 +62,9 b' def difftree(ui, repo, node1=None, node2'
123 if opts['patch']:
62 if opts['patch']:
124 if opts['pretty']:
63 if opts['pretty']:
125 catcommit(repo, node2, "")
64 catcommit(repo, node2, "")
126 dodiff(sys.stdout, ui, repo, node1, node2, files=files)
65 patch.diff(repo, node1, node2,
66 files=files,
67 opts=patch.diffopts(ui, {'git': True}))
127 else:
68 else:
128 __difftree(repo, node1, node2, files=files)
69 __difftree(repo, node1, node2, files=files)
129 if not opts['stdin']:
70 if not opts['stdin']:
@@ -1479,7 +1479,7 b' def fold(ui, repo, *files, **opts):'
1479 if not files:
1479 if not files:
1480 raise util.Abort(_('qfold requires at least one patch name'))
1480 raise util.Abort(_('qfold requires at least one patch name'))
1481 if not q.check_toppatch(repo):
1481 if not q.check_toppatch(repo):
1482 raise util.Abort(_('No patches applied\n'))
1482 raise util.Abort(_('No patches applied'))
1483
1483
1484 message = commands.logmessage(opts)
1484 message = commands.logmessage(opts)
1485 if opts['edit']:
1485 if opts['edit']:
@@ -53,8 +53,8 b' def make_filename(repo, pat, node,'
53 i += 1
53 i += 1
54 return ''.join(newname)
54 return ''.join(newname)
55 except KeyError, inst:
55 except KeyError, inst:
56 raise util.Abort(_("invalid format spec '%%%s' in output file name"),
56 raise util.Abort(_("invalid format spec '%%%s' in output file name") %
57 inst.args[0])
57 inst.args[0])
58
58
59 def make_file(repo, pat, node=None,
59 def make_file(repo, pat, node=None,
60 total=None, seqno=None, revwidth=None, mode='wb', pathname=None):
60 total=None, seqno=None, revwidth=None, mode='wb', pathname=None):
@@ -8,7 +8,7 b''
8 from demandload import demandload
8 from demandload import demandload
9 from node import *
9 from node import *
10 from i18n import gettext as _
10 from i18n import gettext as _
11 demandload(globals(), "os re sys signal shutil imp urllib pdb")
11 demandload(globals(), "os re sys signal shutil imp urllib pdb shlex")
12 demandload(globals(), "fancyopts ui hg util lock revlog templater bundlerepo")
12 demandload(globals(), "fancyopts ui hg util lock revlog templater bundlerepo")
13 demandload(globals(), "fnmatch difflib patch random signal tempfile time")
13 demandload(globals(), "fnmatch difflib patch random signal tempfile time")
14 demandload(globals(), "traceback errno socket version struct atexit sets bz2")
14 demandload(globals(), "traceback errno socket version struct atexit sets bz2")
@@ -274,7 +274,7 b' def revfix(repo, val, defval):'
274 try:
274 try:
275 num = repo.changelog.rev(repo.lookup(val))
275 num = repo.changelog.rev(repo.lookup(val))
276 except KeyError:
276 except KeyError:
277 raise util.Abort(_('invalid revision identifier %s'), val)
277 raise util.Abort(_('invalid revision identifier %s') % val)
278 return num
278 return num
279
279
280 def revpair(ui, repo, revs):
280 def revpair(ui, repo, revs):
@@ -341,7 +341,7 b' def write_bundle(cg, filename=None, comp'
341 try:
341 try:
342 if filename:
342 if filename:
343 if os.path.exists(filename):
343 if os.path.exists(filename):
344 raise util.Abort(_("file '%s' already exists"), filename)
344 raise util.Abort(_("file '%s' already exists") % filename)
345 fh = open(filename, "wb")
345 fh = open(filename, "wb")
346 else:
346 else:
347 fd, filename = tempfile.mkstemp(prefix="hg-bundle-", suffix=".hg")
347 fd, filename = tempfile.mkstemp(prefix="hg-bundle-", suffix=".hg")
@@ -1269,7 +1269,7 b' def debugdata(ui, file_, rev):'
1269 try:
1269 try:
1270 ui.write(r.revision(r.lookup(rev)))
1270 ui.write(r.revision(r.lookup(rev)))
1271 except KeyError:
1271 except KeyError:
1272 raise util.Abort(_('invalid revision identifier %s'), rev)
1272 raise util.Abort(_('invalid revision identifier %s') % rev)
1273
1273
1274 def debugindex(ui, file_):
1274 def debugindex(ui, file_):
1275 """dump the contents of an index file"""
1275 """dump the contents of an index file"""
@@ -1940,7 +1940,7 b' def merge(ui, repo, node=None, force=Non'
1940 revision to merge with must be provided.
1940 revision to merge with must be provided.
1941 """
1941 """
1942
1942
1943 if node:
1943 if node or branch:
1944 node = _lookup(repo, node, branch)
1944 node = _lookup(repo, node, branch)
1945 else:
1945 else:
1946 heads = repo.heads()
1946 heads = repo.heads()
@@ -2484,7 +2484,7 b' def serve(ui, repo, **opts):'
2484 try:
2484 try:
2485 httpd = hgweb.server.create_server(ui, repo)
2485 httpd = hgweb.server.create_server(ui, repo)
2486 except socket.error, inst:
2486 except socket.error, inst:
2487 raise util.Abort(_('cannot start server: ') + inst.args[1])
2487 raise util.Abort(_('cannot start server: %s') % inst.args[1])
2488
2488
2489 if ui.verbose:
2489 if ui.verbose:
2490 addr, port = httpd.socket.getsockname()
2490 addr, port = httpd.socket.getsockname()
@@ -2734,7 +2734,7 b' def _lookup(repo, node, branch=None):'
2734 repo.ui.warn(_("Using head %s for branch %s\n")
2734 repo.ui.warn(_("Using head %s for branch %s\n")
2735 % (short(node), branch))
2735 % (short(node), branch))
2736 else:
2736 else:
2737 raise util.Abort(_("branch %s not found\n") % (branch))
2737 raise util.Abort(_("branch %s not found") % branch)
2738 else:
2738 else:
2739 node = node and repo.lookup(node) or repo.changelog.tip()
2739 node = node and repo.lookup(node) or repo.changelog.tip()
2740 return node
2740 return node
@@ -3223,7 +3223,7 b' def parse(ui, args):'
3223 cmd = aliases[0]
3223 cmd = aliases[0]
3224 defaults = ui.config("defaults", cmd)
3224 defaults = ui.config("defaults", cmd)
3225 if defaults:
3225 if defaults:
3226 args = defaults.split() + args
3226 args = shlex.split(defaults) + args
3227 c = list(i[1])
3227 c = list(i[1])
3228 else:
3228 else:
3229 cmd = None
3229 cmd = None
@@ -3449,7 +3449,7 b' def dispatch(args):'
3449 u.warn(_("abort: could not lock %s: %s\n") %
3449 u.warn(_("abort: could not lock %s: %s\n") %
3450 (inst.desc or inst.filename, inst.strerror))
3450 (inst.desc or inst.filename, inst.strerror))
3451 except revlog.RevlogError, inst:
3451 except revlog.RevlogError, inst:
3452 u.warn(_("abort: "), inst, "!\n")
3452 u.warn(_("abort: %s!\n") % inst)
3453 except util.SignalInterrupt:
3453 except util.SignalInterrupt:
3454 u.warn(_("killed!\n"))
3454 u.warn(_("killed!\n"))
3455 except KeyboardInterrupt:
3455 except KeyboardInterrupt:
@@ -3482,7 +3482,7 b' def dispatch(args):'
3482 else:
3482 else:
3483 u.warn(_("abort: %s\n") % inst.strerror)
3483 u.warn(_("abort: %s\n") % inst.strerror)
3484 except util.Abort, inst:
3484 except util.Abort, inst:
3485 u.warn(_('abort: '), inst.args[0] % inst.args[1:], '\n')
3485 u.warn(_("abort: %s\n") % inst)
3486 except TypeError, inst:
3486 except TypeError, inst:
3487 # was this an argument error?
3487 # was this an argument error?
3488 tb = traceback.extract_tb(sys.exc_info()[2])
3488 tb = traceback.extract_tb(sys.exc_info()[2])
@@ -115,7 +115,7 b' def clone(ui, source, dest=None, pull=Fa'
115 source = localpath(source)
115 source = localpath(source)
116
116
117 if os.path.exists(dest):
117 if os.path.exists(dest):
118 raise util.Abort(_("destination '%s' already exists"), dest)
118 raise util.Abort(_("destination '%s' already exists") % dest)
119
119
120 class DirCleanup(object):
120 class DirCleanup(object):
121 def __init__(self, dir_):
121 def __init__(self, dir_):
@@ -325,7 +325,7 b' class httprepository(remoterepository):'
325 rfp.close()
325 rfp.close()
326 except socket.error, err:
326 except socket.error, err:
327 if err[0] in (errno.ECONNRESET, errno.EPIPE):
327 if err[0] in (errno.ECONNRESET, errno.EPIPE):
328 raise util.Abort(_('push failed: %s'), err[1])
328 raise util.Abort(_('push failed: %s') % err[1])
329 raise util.Abort(err[1])
329 raise util.Abort(err[1])
330 finally:
330 finally:
331 fp.close()
331 fp.close()
@@ -133,7 +133,7 b' class localrepository(repo.repository):'
133 except Exception, exc:
133 except Exception, exc:
134 if isinstance(exc, util.Abort):
134 if isinstance(exc, util.Abort):
135 self.ui.warn(_('error: %s hook failed: %s\n') %
135 self.ui.warn(_('error: %s hook failed: %s\n') %
136 (hname, exc.args[0] % exc.args[1:]))
136 (hname, exc.args[0]))
137 else:
137 else:
138 self.ui.warn(_('error: %s hook raised an exception: '
138 self.ui.warn(_('error: %s hook raised an exception: '
139 '%s\n') % (hname, exc))
139 '%s\n') % (hname, exc))
@@ -502,7 +502,10 b' def diff(repo, node1=None, node2=None, f'
502 header.append('deleted file mode %s\n' % mode)
502 header.append('deleted file mode %s\n' % mode)
503 else:
503 else:
504 omode = gitmode(mmap.execf(f))
504 omode = gitmode(mmap.execf(f))
505 nmode = gitmode(util.is_exec(repo.wjoin(f), mmap.execf(f)))
505 if node2:
506 nmode = gitmode(mmap2.execf(f))
507 else:
508 nmode = gitmode(util.is_exec(repo.wjoin(f), mmap.execf(f)))
506 addmodehdr(header, omode, nmode)
509 addmodehdr(header, omode, nmode)
507 r = None
510 r = None
508 if dodiff:
511 if dodiff:
@@ -122,7 +122,9 b' class ui(object):'
122 try:
122 try:
123 return self.cdata.get(section, name)
123 return self.cdata.get(section, name)
124 except ConfigParser.InterpolationError, inst:
124 except ConfigParser.InterpolationError, inst:
125 raise util.Abort(_("Error in configuration:\n%s") % inst)
125 raise util.Abort(_("Error in configuration section [%s] "
126 "parameter '%s':\n%s")
127 % (section, name, inst))
126 if self.parentui is None:
128 if self.parentui is None:
127 return default
129 return default
128 else:
130 else:
@@ -144,7 +146,9 b' class ui(object):'
144 try:
146 try:
145 return self.cdata.getboolean(section, name)
147 return self.cdata.getboolean(section, name)
146 except ConfigParser.InterpolationError, inst:
148 except ConfigParser.InterpolationError, inst:
147 raise util.Abort(_("Error in configuration:\n%s") % inst)
149 raise util.Abort(_("Error in configuration section [%s] "
150 "parameter '%s':\n%s")
151 % (section, name, inst))
148 if self.parentui is None:
152 if self.parentui is None:
149 return default
153 return default
150 else:
154 else:
@@ -162,7 +166,8 b' class ui(object):'
162 try:
166 try:
163 items.update(dict(self.cdata.items(section)))
167 items.update(dict(self.cdata.items(section)))
164 except ConfigParser.InterpolationError, inst:
168 except ConfigParser.InterpolationError, inst:
165 raise util.Abort(_("Error in configuration:\n%s") % inst)
169 raise util.Abort(_("Error in configuration section [%s]:\n%s")
170 % (section, inst))
166 x = items.items()
171 x = items.items()
167 x.sort()
172 x.sort()
168 return x
173 return x
@@ -174,10 +179,14 b' class ui(object):'
174 yield section, name, value
179 yield section, name, value
175 seen[section, name] = 1
180 seen[section, name] = 1
176 for section in self.cdata.sections():
181 for section in self.cdata.sections():
177 for name, value in self.cdata.items(section):
182 try:
178 if (section, name) in seen: continue
183 for name, value in self.cdata.items(section):
179 yield section, name, value.replace('\n', '\\n')
184 if (section, name) in seen: continue
180 seen[section, name] = 1
185 yield section, name, value.replace('\n', '\\n')
186 seen[section, name] = 1
187 except ConfigParser.InterpolationError, inst:
188 raise util.Abort(_("Error in configuration section [%s]:\n%s")
189 % (section, inst))
181 if self.parentui is not None:
190 if self.parentui is not None:
182 for parent in self.parentui.walkconfig(seen):
191 for parent in self.parentui.walkconfig(seen):
183 yield parent
192 yield parent
@@ -50,3 +50,7 b" hg ci -mrenamemod -d '0 0'"
50 echo '% rename+mod+chmod'
50 echo '% rename+mod+chmod'
51 hg diff --git -r 6:tip | sed -e "s/\(+++ [a-zA-Z0-9_/.-]*\).*/\1/" \
51 hg diff --git -r 6:tip | sed -e "s/\(+++ [a-zA-Z0-9_/.-]*\).*/\1/" \
52 -e "s/\(--- [a-zA-Z0-9_/.-]*\).*/\1/"
52 -e "s/\(--- [a-zA-Z0-9_/.-]*\).*/\1/"
53
54 echo '% nonexistent in tip+chmod'
55 hg diff --git -r 5:6 | sed -e "s/\(+++ [a-zA-Z0-9_/.-]*\).*/\1/" \
56 -e "s/\(--- [a-zA-Z0-9_/.-]*\).*/\1/"
@@ -40,3 +40,7 b' rename to dst'
40 4
40 4
41 5
41 5
42 +a
42 +a
43 % nonexistent in tip+chmod
44 diff --git a/src b/src
45 old mode 100644
46 new mode 100755
@@ -1,6 +1,6 b''
1 #!/usr/bin/env python
1 #!/usr/bin/env python
2
2
3 from mercurial import ui
3 from mercurial import ui, util
4
4
5 testui = ui.ui()
5 testui = ui.ui()
6 testui.updateopts(config=[
6 testui.updateopts(config=[
@@ -11,10 +11,19 b' testui.updateopts(config=['
11 'lists.list2=foo bar baz',
11 'lists.list2=foo bar baz',
12 'lists.list3=alice, bob',
12 'lists.list3=alice, bob',
13 'lists.list4=foo bar baz alice, bob',
13 'lists.list4=foo bar baz alice, bob',
14 'interpolation.value1=hallo',
15 'interpolation.value2=%(value1)s world',
16 'interpolation.value3=%(novalue)s',
17 'interpolation.value4=%(bad)1',
18 'interpolation.value5=%bad2',
14 ])
19 ])
15
20
16 print repr(testui.configitems('values'))
21 print repr(testui.configitems('values'))
17 print repr(testui.configitems('lists'))
22 print repr(testui.configitems('lists'))
23 try:
24 print repr(testui.configitems('interpolation'))
25 except util.Abort, inst:
26 print inst
18 print "---"
27 print "---"
19 print repr(testui.config('values', 'string'))
28 print repr(testui.config('values', 'string'))
20 print repr(testui.config('values', 'bool1'))
29 print repr(testui.config('values', 'bool1'))
@@ -45,3 +54,18 b" print repr(testui.configlist('lists', 'u"
45 print repr(testui.configlist('lists', 'unknown', ['foo bar']))
54 print repr(testui.configlist('lists', 'unknown', ['foo bar']))
46 print repr(testui.configlist('lists', 'unknown', ['foo', 'bar']))
55 print repr(testui.configlist('lists', 'unknown', ['foo', 'bar']))
47 print "---"
56 print "---"
57 print repr(testui.config('interpolation', 'value1'))
58 print repr(testui.config('interpolation', 'value2'))
59 try:
60 print repr(testui.config('interpolation', 'value3'))
61 except util.Abort, inst:
62 print inst
63 try:
64 print repr(testui.config('interpolation', 'value4'))
65 except util.Abort, inst:
66 print inst
67 try:
68 print repr(testui.config('interpolation', 'value5'))
69 except util.Abort, inst:
70 print inst
71 print "---"
@@ -1,5 +1,7 b''
1 [('bool1', 'true'), ('bool2', 'false'), ('string', 'string value')]
1 [('bool1', 'true'), ('bool2', 'false'), ('string', 'string value')]
2 [('list1', 'foo'), ('list2', 'foo bar baz'), ('list3', 'alice, bob'), ('list4', 'foo bar baz alice, bob')]
2 [('list1', 'foo'), ('list2', 'foo bar baz'), ('list3', 'alice, bob'), ('list4', 'foo bar baz alice, bob')]
3 Error in configuration section [interpolation]:
4 '%' must be followed by '%' or '(', found: '%bad2'
3 ---
5 ---
4 'string value'
6 'string value'
5 'true'
7 'true'
@@ -27,3 +29,17 b' True'
27 ['foo bar']
29 ['foo bar']
28 ['foo', 'bar']
30 ['foo', 'bar']
29 ---
31 ---
32 'hallo'
33 'hallo world'
34 Error in configuration section [interpolation] parameter 'value3':
35 Bad value substitution:
36 section: [interpolation]
37 option : value3
38 key : novalue
39 rawval :
40
41 Error in configuration section [interpolation] parameter 'value4':
42 bad interpolation variable reference '%(bad)1'
43 Error in configuration section [interpolation] parameter 'value5':
44 '%' must be followed by '%' or '(', found: '%bad2'
45 ---
General Comments 0
You need to be logged in to leave comments. Login now