556 |
556 |
557 def remove(self, list): |
557 def remove(self, list): |
558 dl = self.opener("to-remove", "a") |
558 dl = self.opener("to-remove", "a") |
559 for f in list: |
559 for f in list: |
560 dl.write(f + "\n") |
560 dl.write(f + "\n") |
|
561 |
|
562 def newer(self, node): |
|
563 nodes = [] |
|
564 for i in xrange(self.changelog.rev(node) + 1, self.changelog.count()): |
|
565 nodes.append(self.changelog.node(i)) |
|
566 |
|
567 return nodes |
|
568 |
|
569 def changegroup(self, nodes): |
|
570 # construct the link map |
|
571 linkmap = {} |
|
572 for n in nodes: |
|
573 linkmap[self.changelog.rev(n)] = n |
|
574 |
|
575 # construct a list of all changed files |
|
576 changed = {} |
|
577 for n in nodes: |
|
578 c = self.changelog.read(n) |
|
579 for f in c[3]: |
|
580 changed[f] = 1 |
|
581 changed = changed.keys() |
|
582 changed.sort() |
|
583 |
|
584 # the changegroup is changesets + manifests + all file revs |
|
585 cg = [] |
|
586 revs = [ self.changelog.rev(n) for n in nodes ] |
|
587 |
|
588 g = self.changelog.group(linkmap) |
|
589 cg.append(g) |
|
590 g = self.manifest.group(linkmap) |
|
591 cg.append(g) |
|
592 |
|
593 for f in changed: |
|
594 g = self.file(f).group(linkmap) |
|
595 if not g: raise "couldn't find change to %s" % f |
|
596 l = struct.pack(">l", len(f)) |
|
597 cg += [l, f, g] |
|
598 |
|
599 return compress("".join(cg)) |
|
600 |
|
601 def addchangegroup(self, data): |
|
602 data = decompress(data) |
|
603 def getlen(data, pos): |
|
604 return struct.unpack(">l", data[pos:pos + 4])[0] |
|
605 |
|
606 tr = self.transaction() |
|
607 simple = True |
|
608 |
|
609 print "merging changesets" |
|
610 # pull off the changeset group |
|
611 l = getlen(data, 0) |
|
612 csg = data[0:l] |
|
613 pos = l |
|
614 co = self.changelog.tip() |
|
615 cn = self.changelog.addgroup(csg, lambda x: self.changelog.count(), tr) |
|
616 |
|
617 print "merging manifests" |
|
618 # pull off the manifest group |
|
619 l = getlen(data, pos) |
|
620 mfg = data[pos: pos + l] |
|
621 pos += l |
|
622 mo = self.manifest.tip() |
|
623 mn = self.manifest.addgroup(mfg, lambda x: self.changelog.rev(x), tr) |
|
624 |
|
625 # do we need a resolve? |
|
626 if self.changelog.ancestor(co, cn) != co: |
|
627 print "NEED RESOLVE" |
|
628 simple = False |
|
629 resolverev = self.changelog.count() |
|
630 |
|
631 # process the files |
|
632 print "merging files" |
|
633 new = {} |
|
634 while pos < len(data): |
|
635 l = getlen(data, pos) |
|
636 pos += 4 |
|
637 f = data[pos:pos + l] |
|
638 pos += l |
|
639 |
|
640 l = getlen(data, pos) |
|
641 fg = data[pos: pos + l] |
|
642 pos += l |
|
643 |
|
644 fl = self.file(f) |
|
645 o = fl.tip() |
|
646 n = fl.addgroup(fg, lambda x: self.changelog.rev(x), tr) |
|
647 if not simple: |
|
648 new[fl] = fl.resolvedag(o, n, tr, resolverev) |
|
649 |
|
650 # For simple merges, we don't need to resolve manifests or changesets |
|
651 if simple: |
|
652 tr.close() |
|
653 return |
|
654 |
|
655 # resolve the manifest to point to all the merged files |
|
656 self.ui.status("resolving manifests\n") |
|
657 ma = self.manifest.ancestor(mm, mo) |
|
658 mmap = self.manifest.read(mm) # mine |
|
659 omap = self.manifest.read(mo) # other |
|
660 amap = self.manifest.read(ma) # ancestor |
|
661 nmap = {} |
|
662 |
|
663 for f, mid in mmap.iteritems(): |
|
664 if f in omap: |
|
665 if mid != omap[f]: |
|
666 nmap[f] = new.get(f, mid) # use merged version |
|
667 else: |
|
668 nmap[f] = new.get(f, mid) # they're the same |
|
669 del omap[f] |
|
670 elif f in amap: |
|
671 if mid != amap[f]: |
|
672 pass # we should prompt here |
|
673 else: |
|
674 pass # other deleted it |
|
675 else: |
|
676 nmap[f] = new.get(f, mid) # we created it |
|
677 |
|
678 del mmap |
|
679 |
|
680 for f, oid in omap.iteritems(): |
|
681 if f in amap: |
|
682 if oid != amap[f]: |
|
683 pass # this is the nasty case, we should prompt |
|
684 else: |
|
685 pass # probably safe |
|
686 else: |
|
687 nmap[f] = new.get(f, oid) # remote created it |
|
688 |
|
689 del omap |
|
690 del amap |
|
691 |
|
692 node = self.manifest.add(nmap, tr, resolverev, mm, mo) |
|
693 |
|
694 # Now all files and manifests are merged, we add the changed files |
|
695 # and manifest id to the changelog |
|
696 self.ui.status("committing merge changeset\n") |
|
697 new = new.keys() |
|
698 new.sort() |
|
699 if co == cn: cn = -1 |
|
700 |
|
701 edittext = "\n"+"".join(["HG: changed %s\n" % f for f in new]) |
|
702 edittext = self.ui.edit(edittext) |
|
703 n = self.changelog.add(node, new, edittext, tr, co, cn) |
|
704 |
|
705 tr.close() |
561 |
706 |
562 class ui: |
707 class ui: |
563 def __init__(self, verbose=False, debug=False): |
708 def __init__(self, verbose=False, debug=False): |
564 self.verbose = verbose |
709 self.verbose = verbose |
565 def write(self, *args): |
710 def write(self, *args): |