Show More
@@ -2218,6 +2218,15 b' def displaygraph(ui, repo, dag, displaye' | |||
|
2218 | 2218 | filematcher=None): |
|
2219 | 2219 | formatnode = _graphnodeformatter(ui, displayer) |
|
2220 | 2220 | state = graphmod.asciistate() |
|
2221 | styles = state['styles'] | |
|
2222 | edgetypes = { | |
|
2223 | 'parent': graphmod.PARENT, | |
|
2224 | 'grandparent': graphmod.GRANDPARENT, | |
|
2225 | 'missing': graphmod.MISSINGPARENT | |
|
2226 | } | |
|
2227 | for name, key in edgetypes.items(): | |
|
2228 | # experimental config: ui.graphstyle.* | |
|
2229 | styles[key] = ui.config('ui', 'graphstyle.%s' % name, styles[key]) | |
|
2221 | 2230 | for rev, type, ctx, parents in dag: |
|
2222 | 2231 | char = formatnode(repo, ctx) |
|
2223 | 2232 | copies = None |
@@ -31,6 +31,7 b" CHANGESET = 'C'" | |||
|
31 | 31 | PARENT = 'P' |
|
32 | 32 | GRANDPARENT = 'G' |
|
33 | 33 | MISSINGPARENT = 'M' |
|
34 | EDGES = {PARENT: '|', GRANDPARENT: '|', MISSINGPARENT: '|'} | |
|
34 | 35 | |
|
35 | 36 | def groupbranchiter(revs, parentsfunc, firstbranch=()): |
|
36 | 37 | """Yield revisions from heads to roots one (topo) branch at a time. |
@@ -390,11 +391,13 b' def asciiedges(type, char, lines, state,' | |||
|
390 | 391 | knownparents.append(parent) |
|
391 | 392 | else: |
|
392 | 393 | newparents.append(parent) |
|
394 | state['edges'][parent] = state['styles'].get(ptype, '|') | |
|
393 | 395 | |
|
394 | 396 | ncols = len(seen) |
|
395 | 397 | nextseen = seen[:] |
|
396 | 398 | nextseen[nodeidx:nodeidx + 1] = newparents |
|
397 |
edges = [(nodeidx, nextseen.index(p)) |
|
|
399 | edges = [(nodeidx, nextseen.index(p)) | |
|
400 | for p in knownparents if p != nullrev] | |
|
398 | 401 | |
|
399 | 402 | while len(newparents) > 2: |
|
400 | 403 | # ascii() only knows how to add or remove a single column between two |
@@ -418,6 +421,8 b' def asciiedges(type, char, lines, state,' | |||
|
418 | 421 | edges.append((nodeidx, nodeidx + 1)) |
|
419 | 422 | nmorecols = len(nextseen) - ncols |
|
420 | 423 | seen[:] = nextseen |
|
424 | # remove current node from edge characters, no longer needed | |
|
425 | state['edges'].pop(rev, None) | |
|
421 | 426 | yield (type, char, lines, (nodeidx, edges, ncols, nmorecols)) |
|
422 | 427 | |
|
423 | 428 | def _fixlongrightedges(edges): |
@@ -426,27 +431,28 b' def _fixlongrightedges(edges):' | |||
|
426 | 431 | edges[i] = (start, end + 1) |
|
427 | 432 | |
|
428 | 433 | def _getnodelineedgestail( |
|
429 |
|
|
|
430 |
if fix_tail and |
|
|
434 | echars, idx, pidx, ncols, coldiff, pdiff, fix_tail): | |
|
435 | if fix_tail and coldiff == pdiff and coldiff != 0: | |
|
431 | 436 | # Still going in the same non-vertical direction. |
|
432 |
if |
|
|
433 |
start = max( |
|
|
434 |
tail = [ |
|
|
435 |
tail.extend(["/", " "] * (n |
|
|
437 | if coldiff == -1: | |
|
438 | start = max(idx + 1, pidx) | |
|
439 | tail = echars[idx * 2:(start - 1) * 2] | |
|
440 | tail.extend(["/", " "] * (ncols - start)) | |
|
436 | 441 | return tail |
|
437 | 442 | else: |
|
438 |
return ["\\", " "] * (n |
|
|
443 | return ["\\", " "] * (ncols - idx - 1) | |
|
439 | 444 | else: |
|
440 |
re |
|
|
445 | remainder = (ncols - idx - 1) | |
|
446 | return echars[-(remainder * 2):] if remainder > 0 else [] | |
|
441 | 447 | |
|
442 | def _drawedges(edges, nodeline, interline): | |
|
448 | def _drawedges(echars, edges, nodeline, interline): | |
|
443 | 449 | for (start, end) in edges: |
|
444 | 450 | if start == end + 1: |
|
445 | 451 | interline[2 * end + 1] = "/" |
|
446 | 452 | elif start == end - 1: |
|
447 | 453 | interline[2 * start + 1] = "\\" |
|
448 | 454 | elif start == end: |
|
449 |
interline[2 * start] = |
|
|
455 | interline[2 * start] = echars[2 * start] | |
|
450 | 456 | else: |
|
451 | 457 | if 2 * end >= len(nodeline): |
|
452 | 458 | continue |
@@ -457,26 +463,35 b' def _drawedges(edges, nodeline, interlin' | |||
|
457 | 463 | if nodeline[i] != "+": |
|
458 | 464 | nodeline[i] = "-" |
|
459 | 465 | |
|
460 |
def _getpaddingline( |
|
|
461 | line = [] | |
|
462 | line.extend(["|", " "] * ni) | |
|
463 | if (ni, ni - 1) in edges or (ni, ni) in edges: | |
|
464 | # (ni, ni - 1) (ni, ni) | |
|
466 | def _getpaddingline(echars, idx, ncols, edges): | |
|
467 | # all edges up to the current node | |
|
468 | line = echars[:idx * 2] | |
|
469 | # an edge for the current node, if there is one | |
|
470 | if (idx, idx - 1) in edges or (idx, idx) in edges: | |
|
471 | # (idx, idx - 1) (idx, idx) | |
|
465 | 472 | # | | | | | | | | |
|
466 | 473 | # +---o | | o---+ |
|
467 |
# | | |
|
|
474 | # | | X | | X | | | |
|
468 | 475 | # | |/ / | |/ / |
|
469 | 476 | # | | | | | | |
|
470 | c = "|" | |
|
477 | line.extend(echars[idx * 2:(idx + 1) * 2]) | |
|
471 | 478 | else: |
|
472 | c = " " | |
|
473 | line.extend([c, " "]) | |
|
474 | line.extend(["|", " "] * (n_columns - ni - 1)) | |
|
479 | line.extend(' ') | |
|
480 | # all edges to the right of the current node | |
|
481 | remainder = ncols - idx - 1 | |
|
482 | if remainder > 0: | |
|
483 | line.extend(echars[-(remainder * 2):]) | |
|
475 | 484 | return line |
|
476 | 485 | |
|
477 | 486 | def asciistate(): |
|
478 | 487 | """returns the initial value for the "state" argument to ascii()""" |
|
479 | return {'seen': [], 'lastcoldiff': 0, 'lastindex': 0} | |
|
488 | return { | |
|
489 | 'seen': [], | |
|
490 | 'edges': {}, | |
|
491 | 'lastcoldiff': 0, | |
|
492 | 'lastindex': 0, | |
|
493 | 'styles': EDGES.copy(), | |
|
494 | } | |
|
480 | 495 | |
|
481 | 496 | def ascii(ui, state, type, char, text, coldata): |
|
482 | 497 | """prints an ASCII graph of the DAG |
@@ -498,9 +513,15 b' def ascii(ui, state, type, char, text, c' | |||
|
498 | 513 | in the current revision. That is: -1 means one column removed; |
|
499 | 514 | 0 means no columns added or removed; 1 means one column added. |
|
500 | 515 | """ |
|
501 | ||
|
502 | 516 | idx, edges, ncols, coldiff = coldata |
|
503 | 517 | assert -2 < coldiff < 2 |
|
518 | ||
|
519 | edgemap, seen = state['edges'], state['seen'] | |
|
520 | # Be tolerant of history issues; make sure we have at least ncols + coldiff | |
|
521 | # elements to work with. See test-glog.t for broken history test cases. | |
|
522 | echars = [c for p in seen for c in (edgemap.get(p, '|'), ' ')] | |
|
523 | echars.extend(('|', ' ') * max(ncols + coldiff - len(seen), 0)) | |
|
524 | ||
|
504 | 525 | if coldiff == -1: |
|
505 | 526 | # Transform |
|
506 | 527 | # |
@@ -530,35 +551,33 b' def ascii(ui, state, type, char, text, c' | |||
|
530 | 551 | fix_nodeline_tail = len(text) <= 2 and not add_padding_line |
|
531 | 552 | |
|
532 | 553 | # nodeline is the line containing the node character (typically o) |
|
533 |
nodeline = [ |
|
|
554 | nodeline = echars[:idx * 2] | |
|
534 | 555 | nodeline.extend([char, " "]) |
|
535 | 556 | |
|
536 | 557 | nodeline.extend( |
|
537 |
_getnodelineedgestail( |
|
|
538 | state['lastcoldiff'], fix_nodeline_tail)) | |
|
558 | _getnodelineedgestail( | |
|
559 | echars, idx, state['lastindex'], ncols, coldiff, | |
|
560 | state['lastcoldiff'], fix_nodeline_tail)) | |
|
539 | 561 | |
|
540 | 562 | # shift_interline is the line containing the non-vertical |
|
541 | 563 | # edges between this entry and the next |
|
542 |
shift_interline = [ |
|
|
564 | shift_interline = echars[:idx * 2] | |
|
565 | shift_interline.extend(' ' * (2 + coldiff)) | |
|
566 | count = ncols - idx - 1 | |
|
543 | 567 | if coldiff == -1: |
|
544 | n_spaces = 1 | |
|
545 | edge_ch = "/" | |
|
568 | shift_interline.extend('/ ' * count) | |
|
546 | 569 | elif coldiff == 0: |
|
547 | n_spaces = 2 | |
|
548 | edge_ch = "|" | |
|
570 | shift_interline.extend(echars[(idx + 1) * 2:ncols * 2]) | |
|
549 | 571 | else: |
|
550 | n_spaces = 3 | |
|
551 | edge_ch = "\\" | |
|
552 | shift_interline.extend(n_spaces * [" "]) | |
|
553 | shift_interline.extend([edge_ch, " "] * (ncols - idx - 1)) | |
|
572 | shift_interline.extend(r'\ ' * count) | |
|
554 | 573 | |
|
555 | 574 | # draw edges from the current node to its parents |
|
556 | _drawedges(edges, nodeline, shift_interline) | |
|
575 | _drawedges(echars, edges, nodeline, shift_interline) | |
|
557 | 576 | |
|
558 | 577 | # lines is the list of all graph lines to print |
|
559 | 578 | lines = [nodeline] |
|
560 | 579 | if add_padding_line: |
|
561 | lines.append(_getpaddingline(idx, ncols, edges)) | |
|
580 | lines.append(_getpaddingline(echars, idx, ncols, edges)) | |
|
562 | 581 | lines.append(shift_interline) |
|
563 | 582 | |
|
564 | 583 | # make sure that there are as many graph lines as there are |
@@ -566,7 +585,7 b' def ascii(ui, state, type, char, text, c' | |||
|
566 | 585 | while len(text) < len(lines): |
|
567 | 586 | text.append("") |
|
568 | 587 | if len(lines) < len(text): |
|
569 |
extra_interline = [ |
|
|
588 | extra_interline = echars[:(ncols + coldiff) * 2] | |
|
570 | 589 | while len(lines) < len(text): |
|
571 | 590 | lines.append(extra_interline) |
|
572 | 591 |
@@ -2415,3 +2415,214 b' label() should just work in node templat' | |||
|
2415 | 2415 | | |
|
2416 | 2416 | |
|
2417 | 2417 | $ cd .. |
|
2418 | ||
|
2419 | change graph edge styling | |
|
2420 | ||
|
2421 | $ cd repo | |
|
2422 | $ cat << EOF >> $HGRCPATH | |
|
2423 | > [ui] | |
|
2424 | > graphstyle.parent = | | |
|
2425 | > graphstyle.grandparent = : | |
|
2426 | > graphstyle.missing = . | |
|
2427 | > EOF | |
|
2428 | $ hg log -G -r 'file("a")' -m | |
|
2429 | @ changeset: 36:08a19a744424 | |
|
2430 | : branch: branch | |
|
2431 | : tag: tip | |
|
2432 | : parent: 35:9159c3644c5e | |
|
2433 | : parent: 35:9159c3644c5e | |
|
2434 | : user: test | |
|
2435 | : date: Thu Jan 01 00:00:36 1970 +0000 | |
|
2436 | : summary: (36) buggy merge: identical parents | |
|
2437 | : | |
|
2438 | o changeset: 32:d06dffa21a31 | |
|
2439 | |\ parent: 27:886ed638191b | |
|
2440 | | : parent: 31:621d83e11f67 | |
|
2441 | | : user: test | |
|
2442 | | : date: Thu Jan 01 00:00:32 1970 +0000 | |
|
2443 | | : summary: (32) expand | |
|
2444 | | : | |
|
2445 | o : changeset: 31:621d83e11f67 | |
|
2446 | |\: parent: 21:d42a756af44d | |
|
2447 | | : parent: 30:6e11cd4b648f | |
|
2448 | | : user: test | |
|
2449 | | : date: Thu Jan 01 00:00:31 1970 +0000 | |
|
2450 | | : summary: (31) expand | |
|
2451 | | : | |
|
2452 | o : changeset: 30:6e11cd4b648f | |
|
2453 | |\ \ parent: 28:44ecd0b9ae99 | |
|
2454 | | . : parent: 29:cd9bb2be7593 | |
|
2455 | | . : user: test | |
|
2456 | | . : date: Thu Jan 01 00:00:30 1970 +0000 | |
|
2457 | | . : summary: (30) expand | |
|
2458 | | . : | |
|
2459 | o . : changeset: 28:44ecd0b9ae99 | |
|
2460 | |\ \ \ parent: 1:6db2ef61d156 | |
|
2461 | | . . : parent: 26:7f25b6c2f0b9 | |
|
2462 | | . . : user: test | |
|
2463 | | . . : date: Thu Jan 01 00:00:28 1970 +0000 | |
|
2464 | | . . : summary: (28) merge zero known | |
|
2465 | | . . : | |
|
2466 | o . . : changeset: 26:7f25b6c2f0b9 | |
|
2467 | |\ \ \ \ parent: 18:1aa84d96232a | |
|
2468 | | | . . : parent: 25:91da8ed57247 | |
|
2469 | | | . . : user: test | |
|
2470 | | | . . : date: Thu Jan 01 00:00:26 1970 +0000 | |
|
2471 | | | . . : summary: (26) merge one known; far right | |
|
2472 | | | . . : | |
|
2473 | | o-----+ changeset: 25:91da8ed57247 | |
|
2474 | | | . . : parent: 21:d42a756af44d | |
|
2475 | | | . . : parent: 24:a9c19a3d96b7 | |
|
2476 | | | . . : user: test | |
|
2477 | | | . . : date: Thu Jan 01 00:00:25 1970 +0000 | |
|
2478 | | | . . : summary: (25) merge one known; far left | |
|
2479 | | | . . : | |
|
2480 | | o . . : changeset: 24:a9c19a3d96b7 | |
|
2481 | | |\ \ \ \ parent: 0:e6eb3150255d | |
|
2482 | | | . . . : parent: 23:a01cddf0766d | |
|
2483 | | | . . . : user: test | |
|
2484 | | | . . . : date: Thu Jan 01 00:00:24 1970 +0000 | |
|
2485 | | | . . . : summary: (24) merge one known; immediate right | |
|
2486 | | | . . . : | |
|
2487 | | o---+ . : changeset: 23:a01cddf0766d | |
|
2488 | | | . . . : parent: 1:6db2ef61d156 | |
|
2489 | | | . . . : parent: 22:e0d9cccacb5d | |
|
2490 | | | . . . : user: test | |
|
2491 | | | . . . : date: Thu Jan 01 00:00:23 1970 +0000 | |
|
2492 | | | . . . : summary: (23) merge one known; immediate left | |
|
2493 | | | . . . : | |
|
2494 | | o-------+ changeset: 22:e0d9cccacb5d | |
|
2495 | | . . . . : parent: 18:1aa84d96232a | |
|
2496 | |/ / / / / parent: 21:d42a756af44d | |
|
2497 | | . . . : user: test | |
|
2498 | | . . . : date: Thu Jan 01 00:00:22 1970 +0000 | |
|
2499 | | . . . : summary: (22) merge two known; one far left, one far right | |
|
2500 | | . . . : | |
|
2501 | | . . . o changeset: 21:d42a756af44d | |
|
2502 | | . . . |\ parent: 19:31ddc2c1573b | |
|
2503 | | . . . | | parent: 20:d30ed6450e32 | |
|
2504 | | . . . | | user: test | |
|
2505 | | . . . | | date: Thu Jan 01 00:00:21 1970 +0000 | |
|
2506 | | . . . | | summary: (21) expand | |
|
2507 | | . . . | | | |
|
2508 | +-+-------o changeset: 20:d30ed6450e32 | |
|
2509 | | . . . | parent: 0:e6eb3150255d | |
|
2510 | | . . . | parent: 18:1aa84d96232a | |
|
2511 | | . . . | user: test | |
|
2512 | | . . . | date: Thu Jan 01 00:00:20 1970 +0000 | |
|
2513 | | . . . | summary: (20) merge two known; two far right | |
|
2514 | | . . . | | |
|
2515 | | . . . o changeset: 19:31ddc2c1573b | |
|
2516 | | . . . |\ parent: 15:1dda3f72782d | |
|
2517 | | . . . | | parent: 17:44765d7c06e0 | |
|
2518 | | . . . | | user: test | |
|
2519 | | . . . | | date: Thu Jan 01 00:00:19 1970 +0000 | |
|
2520 | | . . . | | summary: (19) expand | |
|
2521 | | . . . | | | |
|
2522 | o---+---+ | changeset: 18:1aa84d96232a | |
|
2523 | . . . | | parent: 1:6db2ef61d156 | |
|
2524 | / / / / / parent: 15:1dda3f72782d | |
|
2525 | . . . | | user: test | |
|
2526 | . . . | | date: Thu Jan 01 00:00:18 1970 +0000 | |
|
2527 | . . . | | summary: (18) merge two known; two far left | |
|
2528 | . . . | | | |
|
2529 | . . . | o changeset: 17:44765d7c06e0 | |
|
2530 | . . . | |\ parent: 12:86b91144a6e9 | |
|
2531 | . . . | | | parent: 16:3677d192927d | |
|
2532 | . . . | | | user: test | |
|
2533 | . . . | | | date: Thu Jan 01 00:00:17 1970 +0000 | |
|
2534 | . . . | | | summary: (17) expand | |
|
2535 | . . . | | | | |
|
2536 | +-+-------o changeset: 16:3677d192927d | |
|
2537 | . . . | | parent: 0:e6eb3150255d | |
|
2538 | . . . | | parent: 1:6db2ef61d156 | |
|
2539 | . . . | | user: test | |
|
2540 | . . . | | date: Thu Jan 01 00:00:16 1970 +0000 | |
|
2541 | . . . | | summary: (16) merge two known; one immediate right, one near right | |
|
2542 | . . . | | | |
|
2543 | . . . o | changeset: 15:1dda3f72782d | |
|
2544 | . . . |\ \ parent: 13:22d8966a97e3 | |
|
2545 | . . . | | | parent: 14:8eac370358ef | |
|
2546 | . . . | | | user: test | |
|
2547 | . . . | | | date: Thu Jan 01 00:00:15 1970 +0000 | |
|
2548 | . . . | | | summary: (15) expand | |
|
2549 | . . . | | | | |
|
2550 | +-------o | changeset: 14:8eac370358ef | |
|
2551 | . . . | |/ parent: 0:e6eb3150255d | |
|
2552 | . . . | | parent: 12:86b91144a6e9 | |
|
2553 | . . . | | user: test | |
|
2554 | . . . | | date: Thu Jan 01 00:00:14 1970 +0000 | |
|
2555 | . . . | | summary: (14) merge two known; one immediate right, one far right | |
|
2556 | . . . | | | |
|
2557 | . . . o | changeset: 13:22d8966a97e3 | |
|
2558 | . . . |\ \ parent: 9:7010c0af0a35 | |
|
2559 | . . . | | | parent: 11:832d76e6bdf2 | |
|
2560 | . . . | | | user: test | |
|
2561 | . . . | | | date: Thu Jan 01 00:00:13 1970 +0000 | |
|
2562 | . . . | | | summary: (13) expand | |
|
2563 | . . . | | | | |
|
2564 | . +---+---o changeset: 12:86b91144a6e9 | |
|
2565 | . . . | | parent: 1:6db2ef61d156 | |
|
2566 | . . . | | parent: 9:7010c0af0a35 | |
|
2567 | . . . | | user: test | |
|
2568 | . . . | | date: Thu Jan 01 00:00:12 1970 +0000 | |
|
2569 | . . . | | summary: (12) merge two known; one immediate right, one far left | |
|
2570 | . . . | | | |
|
2571 | . . . | o changeset: 11:832d76e6bdf2 | |
|
2572 | . . . | |\ parent: 6:b105a072e251 | |
|
2573 | . . . | | | parent: 10:74c64d036d72 | |
|
2574 | . . . | | | user: test | |
|
2575 | . . . | | | date: Thu Jan 01 00:00:11 1970 +0000 | |
|
2576 | . . . | | | summary: (11) expand | |
|
2577 | . . . | | | | |
|
2578 | +---------o changeset: 10:74c64d036d72 | |
|
2579 | . . . | |/ parent: 0:e6eb3150255d | |
|
2580 | . . . | | parent: 6:b105a072e251 | |
|
2581 | . . . | | user: test | |
|
2582 | . . . | | date: Thu Jan 01 00:00:10 1970 +0000 | |
|
2583 | . . . | | summary: (10) merge two known; one immediate left, one near right | |
|
2584 | . . . | | | |
|
2585 | . . . o | changeset: 9:7010c0af0a35 | |
|
2586 | . . . |\ \ parent: 7:b632bb1b1224 | |
|
2587 | . . . | | | parent: 8:7a0b11f71937 | |
|
2588 | . . . | | | user: test | |
|
2589 | . . . | | | date: Thu Jan 01 00:00:09 1970 +0000 | |
|
2590 | . . . | | | summary: (9) expand | |
|
2591 | . . . | | | | |
|
2592 | +-------o | changeset: 8:7a0b11f71937 | |
|
2593 | . . . |/ / parent: 0:e6eb3150255d | |
|
2594 | . . . | | parent: 7:b632bb1b1224 | |
|
2595 | . . . | | user: test | |
|
2596 | . . . | | date: Thu Jan 01 00:00:08 1970 +0000 | |
|
2597 | . . . | | summary: (8) merge two known; one immediate left, one far right | |
|
2598 | . . . | | | |
|
2599 | . . . o | changeset: 7:b632bb1b1224 | |
|
2600 | . . . |\ \ parent: 2:3d9a33b8d1e1 | |
|
2601 | . . . | . | parent: 5:4409d547b708 | |
|
2602 | . . . | . | user: test | |
|
2603 | . . . | . | date: Thu Jan 01 00:00:07 1970 +0000 | |
|
2604 | . . . | . | summary: (7) expand | |
|
2605 | . . . | . | | |
|
2606 | . . . +---o changeset: 6:b105a072e251 | |
|
2607 | . . . | ./ parent: 2:3d9a33b8d1e1 | |
|
2608 | . . . | . parent: 5:4409d547b708 | |
|
2609 | . . . | . user: test | |
|
2610 | . . . | . date: Thu Jan 01 00:00:06 1970 +0000 | |
|
2611 | . . . | . summary: (6) merge two known; one immediate left, one far left | |
|
2612 | . . . | . | |
|
2613 | . . . o . changeset: 5:4409d547b708 | |
|
2614 | . . . |\ \ parent: 3:27eef8ed80b4 | |
|
2615 | . . . | . . parent: 4:26a8bac39d9f | |
|
2616 | . . . | . . user: test | |
|
2617 | . . . | . . date: Thu Jan 01 00:00:05 1970 +0000 | |
|
2618 | . . . | . . summary: (5) expand | |
|
2619 | . . . | . . | |
|
2620 | . +---o . . changeset: 4:26a8bac39d9f | |
|
2621 | . . . ./ / parent: 1:6db2ef61d156 | |
|
2622 | . . . . . parent: 3:27eef8ed80b4 | |
|
2623 | . . . . . user: test | |
|
2624 | . . . . . date: Thu Jan 01 00:00:04 1970 +0000 | |
|
2625 | . . . . . summary: (4) merge two known; one immediate left, one immediate right | |
|
2626 | . . . . . | |
|
2627 | ||
|
2628 | $ cd .. |
General Comments 0
You need to be logged in to leave comments.
Login now