17 if not path: |
17 if not path: |
18 p = os.getcwd() |
18 p = os.getcwd() |
19 while not os.path.isdir(os.path.join(p, ".hg")): |
19 while not os.path.isdir(os.path.join(p, ".hg")): |
20 oldp = p |
20 oldp = p |
21 p = os.path.dirname(p) |
21 p = os.path.dirname(p) |
22 if p == oldp: raise repo.RepoError(_("no repo found")) |
22 if p == oldp: |
|
23 raise repo.RepoError(_("no repo found")) |
23 path = p |
24 path = p |
24 self.path = os.path.join(path, ".hg") |
25 self.path = os.path.join(path, ".hg") |
25 |
26 |
26 if not create and not os.path.isdir(self.path): |
27 if not create and not os.path.isdir(self.path): |
27 raise repo.RepoError(_("repository %s not found") % path) |
28 raise repo.RepoError(_("repository %s not found") % path) |
42 os.mkdir(self.join("data")) |
43 os.mkdir(self.join("data")) |
43 |
44 |
44 self.dirstate = dirstate.dirstate(self.opener, ui, self.root) |
45 self.dirstate = dirstate.dirstate(self.opener, ui, self.root) |
45 try: |
46 try: |
46 self.ui.readconfig(self.join("hgrc")) |
47 self.ui.readconfig(self.join("hgrc")) |
47 except IOError: pass |
48 except IOError: |
|
49 pass |
48 |
50 |
49 def hook(self, name, **args): |
51 def hook(self, name, **args): |
50 def runhook(name, cmd): |
52 def runhook(name, cmd): |
51 self.ui.note(_("running hook %s: %s\n") % (name, cmd)) |
53 self.ui.note(_("running hook %s: %s\n") % (name, cmd)) |
52 old = {} |
54 old = {} |
124 for t, n in self.tags().items(): |
126 for t, n in self.tags().items(): |
125 try: |
127 try: |
126 r = self.changelog.rev(n) |
128 r = self.changelog.rev(n) |
127 except: |
129 except: |
128 r = -2 # sort to the beginning of the list if unknown |
130 r = -2 # sort to the beginning of the list if unknown |
129 l.append((r,t,n)) |
131 l.append((r, t, n)) |
130 l.sort() |
132 l.sort() |
131 return [(t,n) for r,t,n in l] |
133 return [(t, n) for r, t, n in l] |
132 |
134 |
133 def nodetags(self, node): |
135 def nodetags(self, node): |
134 '''return the tags associated with a node''' |
136 '''return the tags associated with a node''' |
135 if not self.nodetagscache: |
137 if not self.nodetagscache: |
136 self.nodetagscache = {} |
138 self.nodetagscache = {} |
137 for t,n in self.tags().items(): |
139 for t, n in self.tags().items(): |
138 self.nodetagscache.setdefault(n,[]).append(t) |
140 self.nodetagscache.setdefault(n, []).append(t) |
139 return self.nodetagscache.get(node, []) |
141 return self.nodetagscache.get(node, []) |
140 |
142 |
141 def lookup(self, key): |
143 def lookup(self, key): |
142 try: |
144 try: |
143 return self.tags()[key] |
145 return self.tags()[key] |
334 n = self.changelog.add(mnode, changed, text, tr, p1, p2, user, date) |
337 n = self.changelog.add(mnode, changed, text, tr, p1, p2, user, date) |
335 tr.close() |
338 tr.close() |
336 if update_dirstate: |
339 if update_dirstate: |
337 self.dirstate.setparents(n, nullid) |
340 self.dirstate.setparents(n, nullid) |
338 |
341 |
339 def commit(self, files = None, text = "", user = None, date = None, |
342 def commit(self, files=None, text="", user=None, date=None, |
340 match = util.always, force=False): |
343 match=util.always, force=False): |
341 commit = [] |
344 commit = [] |
342 remove = [] |
345 remove = [] |
343 changed = [] |
346 changed = [] |
344 |
347 |
345 if files: |
348 if files: |
470 util.pathto(self.getcwd(), fn), short(node))) |
473 util.pathto(self.getcwd(), fn), short(node))) |
471 else: |
474 else: |
472 for src, fn in self.dirstate.walk(files, match): |
475 for src, fn in self.dirstate.walk(files, match): |
473 yield src, fn |
476 yield src, fn |
474 |
477 |
475 def changes(self, node1 = None, node2 = None, files = [], |
478 def changes(self, node1=None, node2=None, files=[], match=util.always): |
476 match = util.always): |
|
477 mf2, u = None, [] |
479 mf2, u = None, [] |
478 |
480 |
479 def fcmp(fn, mf): |
481 def fcmp(fn, mf): |
480 t1 = self.wread(fn) |
482 t1 = self.wread(fn) |
481 t2 = self.file(fn).read(mf.get(fn, nullid)) |
483 t2 = self.file(fn).read(mf.get(fn, nullid)) |
520 change = self.changelog.read(self.dirstate.parents()[0]) |
522 change = self.changelog.read(self.dirstate.parents()[0]) |
521 mf2 = mfmatches(change[0]) |
523 mf2 = mfmatches(change[0]) |
522 for f in a + c + l: |
524 for f in a + c + l: |
523 mf2[f] = "" |
525 mf2[f] = "" |
524 for f in d: |
526 for f in d: |
525 if f in mf2: del mf2[f] |
527 if f in mf2: |
|
528 del mf2[f] |
526 else: |
529 else: |
527 change = self.changelog.read(node2) |
530 change = self.changelog.read(node2) |
528 mf2 = mfmatches(change[0]) |
531 mf2 = mfmatches(change[0]) |
529 |
532 |
530 # flush lists from dirstate before comparing manifests |
533 # flush lists from dirstate before comparing manifests |
554 for f in list: |
557 for f in list: |
555 p = self.wjoin(f) |
558 p = self.wjoin(f) |
556 if not os.path.exists(p): |
559 if not os.path.exists(p): |
557 self.ui.warn(_("%s does not exist!\n") % f) |
560 self.ui.warn(_("%s does not exist!\n") % f) |
558 elif not os.path.isfile(p): |
561 elif not os.path.isfile(p): |
559 self.ui.warn(_("%s not added: only files supported currently\n") % f) |
562 self.ui.warn(_("%s not added: only files supported currently\n") |
|
563 % f) |
560 elif self.dirstate.state(f) in 'an': |
564 elif self.dirstate.state(f) in 'an': |
561 self.ui.warn(_("%s already tracked!\n") % f) |
565 self.ui.warn(_("%s already tracked!\n") % f) |
562 else: |
566 else: |
563 self.dirstate.update([f], "a") |
567 self.dirstate.update([f], "a") |
564 |
568 |
574 if unlink: |
578 if unlink: |
575 for f in list: |
579 for f in list: |
576 try: |
580 try: |
577 util.unlink(self.wjoin(f)) |
581 util.unlink(self.wjoin(f)) |
578 except OSError, inst: |
582 except OSError, inst: |
579 if inst.errno != errno.ENOENT: raise |
583 if inst.errno != errno.ENOENT: |
|
584 raise |
580 wlock = self.wlock() |
585 wlock = self.wlock() |
581 for f in list: |
586 for f in list: |
582 p = self.wjoin(f) |
587 p = self.wjoin(f) |
583 if os.path.exists(p): |
588 if os.path.exists(p): |
584 self.ui.warn(_("%s still exists!\n") % f) |
589 self.ui.warn(_("%s still exists!\n") % f) |
729 l = out.setdefault(h, []) |
734 l = out.setdefault(h, []) |
730 l[len(l):] = self.nodetags(b) |
735 l[len(l):] = self.nodetags(b) |
731 return out |
736 return out |
732 |
737 |
733 def branches(self, nodes): |
738 def branches(self, nodes): |
734 if not nodes: nodes = [self.changelog.tip()] |
739 if not nodes: |
|
740 nodes = [self.changelog.tip()] |
735 b = [] |
741 b = [] |
736 for n in nodes: |
742 for n in nodes: |
737 t = n |
743 t = n |
738 while n: |
744 while n: |
739 p = self.changelog.parents(n) |
745 p = self.changelog.parents(n) |
837 for p in range(0, len(r), 10): |
844 for p in range(0, len(r), 10): |
838 for b in remote.branches(r[p:p+10]): |
845 for b in remote.branches(r[p:p+10]): |
839 self.ui.debug(_("received %s:%s\n") % |
846 self.ui.debug(_("received %s:%s\n") % |
840 (short(b[0]), short(b[1]))) |
847 (short(b[0]), short(b[1]))) |
841 if b[0] in m: |
848 if b[0] in m: |
842 self.ui.debug(_("found base node %s\n") % short(b[0])) |
849 self.ui.debug(_("found base node %s\n") |
|
850 % short(b[0])) |
843 base[b[0]] = 1 |
851 base[b[0]] = 1 |
844 elif b[0] not in seen: |
852 elif b[0] not in seen: |
845 unknown.append(b) |
853 unknown.append(b) |
846 |
854 |
847 # do binary search on the branches we found |
855 # do binary search on the branches we found |
910 subset.append(n) |
918 subset.append(n) |
911 |
919 |
912 # this is the set of all roots we have to push |
920 # this is the set of all roots we have to push |
913 return subset |
921 return subset |
914 |
922 |
915 def pull(self, remote, heads = None): |
923 def pull(self, remote, heads=None): |
916 lock = self.lock() |
924 lock = self.lock() |
917 |
925 |
918 # if we have an empty repo, fetch everything |
926 # if we have an empty repo, fetch everything |
919 if self.changelog.tip() == nullid: |
927 if self.changelog.tip() == nullid: |
920 self.ui.status(_("requesting all changes\n")) |
928 self.ui.status(_("requesting all changes\n")) |
1281 |
1289 |
1282 def addchangegroup(self, source): |
1290 def addchangegroup(self, source): |
1283 |
1291 |
1284 def getchunk(): |
1292 def getchunk(): |
1285 d = source.read(4) |
1293 d = source.read(4) |
1286 if not d: return "" |
1294 if not d: |
|
1295 return "" |
1287 l = struct.unpack(">l", d)[0] |
1296 l = struct.unpack(">l", d)[0] |
1288 if l <= 4: return "" |
1297 if l <= 4: |
|
1298 return "" |
1289 d = source.read(l - 4) |
1299 d = source.read(l - 4) |
1290 if len(d) < l - 4: |
1300 if len(d) < l - 4: |
1291 raise repo.RepoError(_("premature EOF reading chunk" |
1301 raise repo.RepoError(_("premature EOF reading chunk" |
1292 " (got %d bytes, expected %d)") |
1302 " (got %d bytes, expected %d)") |
1293 % (len(d), l - 4)) |
1303 % (len(d), l - 4)) |
1294 return d |
1304 return d |
1295 |
1305 |
1296 def getgroup(): |
1306 def getgroup(): |
1297 while 1: |
1307 while 1: |
1298 c = getchunk() |
1308 c = getchunk() |
1299 if not c: break |
1309 if not c: |
|
1310 break |
1300 yield c |
1311 yield c |
1301 |
1312 |
1302 def csmap(x): |
1313 def csmap(x): |
1303 self.ui.debug(_("add changeset %s\n") % short(x)) |
1314 self.ui.debug(_("add changeset %s\n") % short(x)) |
1304 return self.changelog.count() |
1315 return self.changelog.count() |
1305 |
1316 |
1306 def revmap(x): |
1317 def revmap(x): |
1307 return self.changelog.rev(x) |
1318 return self.changelog.rev(x) |
1308 |
1319 |
1309 if not source: return |
1320 if not source: |
|
1321 return |
1310 changesets = files = revisions = 0 |
1322 changesets = files = revisions = 0 |
1311 |
1323 |
1312 tr = self.transaction() |
1324 tr = self.transaction() |
1313 |
1325 |
1314 oldheads = len(self.changelog.heads()) |
1326 oldheads = len(self.changelog.heads()) |
1350 |
1363 |
1351 tr.close() |
1364 tr.close() |
1352 |
1365 |
1353 if changesets > 0: |
1366 if changesets > 0: |
1354 if not self.hook("changegroup", |
1367 if not self.hook("changegroup", |
1355 node=hex(self.changelog.node(cor+1))): |
1368 node=hex(self.changelog.node(cor+1))): |
1356 self.ui.warn(_("abort: changegroup hook returned failure!\n")) |
1369 self.ui.warn(_("abort: changegroup hook returned failure!\n")) |
1357 return 1 |
1370 return 1 |
1358 |
1371 |
1359 for i in range(cor + 1, cnr + 1): |
1372 for i in range(cor + 1, cnr + 1): |
1360 self.hook("commit", node=hex(self.changelog.node(i))) |
1373 self.hook("commit", node=hex(self.changelog.node(i))) |
1386 if c or a or d: |
1399 if c or a or d: |
1387 raise util.Abort(_("outstanding uncommited changes")) |
1400 raise util.Abort(_("outstanding uncommited changes")) |
1388 if not forcemerge and not force: |
1401 if not forcemerge and not force: |
1389 for f in u: |
1402 for f in u: |
1390 if f in m2: |
1403 if f in m2: |
1391 t1 = self.wread(f) |
1404 t1 = self.wread(f) |
1392 t2 = self.file(f).read(m2[f]) |
1405 t2 = self.file(f).read(m2[f]) |
1393 if cmp(t1, t2) != 0: |
1406 if cmp(t1, t2) != 0: |
1394 raise util.Abort(_("'%s' already exists in the working" |
1407 raise util.Abort(_("'%s' already exists in the working" |
1395 " dir and differs from remote") % f) |
1408 " dir and differs from remote") % f) |
1396 |
1409 |
1397 # is this a jump, or a merge? i.e. is there a linear path |
1410 # is this a jump, or a merge? i.e. is there a linear path |
1398 # from p1 to p2? |
1411 # from p1 to p2? |
1421 |
1434 |
1422 if moddirstate: |
1435 if moddirstate: |
1423 wlock = self.wlock() |
1436 wlock = self.wlock() |
1424 |
1437 |
1425 for f in d: |
1438 for f in d: |
1426 if f in mw: del mw[f] |
1439 if f in mw: |
|
1440 del mw[f] |
1427 |
1441 |
1428 # If we're jumping between revisions (as opposed to merging), |
1442 # If we're jumping between revisions (as opposed to merging), |
1429 # and if neither the working directory nor the target rev has |
1443 # and if neither the working directory nor the target rev has |
1430 # the file, then we need to remove it from the dirstate, to |
1444 # the file, then we need to remove it from the dirstate, to |
1431 # prevent the dirstate from listing the file when it is no |
1445 # prevent the dirstate from listing the file when it is no |
1433 if moddirstate and linear_path and f not in m2: |
1447 if moddirstate and linear_path and f not in m2: |
1434 self.dirstate.forget((f,)) |
1448 self.dirstate.forget((f,)) |
1435 |
1449 |
1436 # Compare manifests |
1450 # Compare manifests |
1437 for f, n in mw.iteritems(): |
1451 for f, n in mw.iteritems(): |
1438 if choose and not choose(f): continue |
1452 if choose and not choose(f): |
|
1453 continue |
1439 if f in m2: |
1454 if f in m2: |
1440 s = 0 |
1455 s = 0 |
1441 |
1456 |
1442 # is the wfile new since m1, and match m2? |
1457 # is the wfile new since m1, and match m2? |
1443 if f not in m1: |
1458 if f not in m1: |
1476 util.set_exec(self.wjoin(f), mf2[f]) |
1491 util.set_exec(self.wjoin(f), mf2[f]) |
1477 else: |
1492 else: |
1478 a, b, c = mfa.get(f, 0), mfw[f], mf2[f] |
1493 a, b, c = mfa.get(f, 0), mfw[f], mf2[f] |
1479 mode = ((a^b) | (a^c)) ^ a |
1494 mode = ((a^b) | (a^c)) ^ a |
1480 if mode != b: |
1495 if mode != b: |
1481 self.ui.debug(_(" updating permissions for %s\n") % f) |
1496 self.ui.debug(_(" updating permissions for %s\n") |
|
1497 % f) |
1482 util.set_exec(self.wjoin(f), mode) |
1498 util.set_exec(self.wjoin(f), mode) |
1483 del m2[f] |
1499 del m2[f] |
1484 elif f in ma: |
1500 elif f in ma: |
1485 if n != ma[f]: |
1501 if n != ma[f]: |
1486 r = _("d") |
1502 r = _("d") |
1506 self.ui.debug(_("local modified %s, keeping\n") % f) |
1522 self.ui.debug(_("local modified %s, keeping\n") % f) |
1507 else: |
1523 else: |
1508 self.ui.debug(_("working dir created %s, keeping\n") % f) |
1524 self.ui.debug(_("working dir created %s, keeping\n") % f) |
1509 |
1525 |
1510 for f, n in m2.iteritems(): |
1526 for f, n in m2.iteritems(): |
1511 if choose and not choose(f): continue |
1527 if choose and not choose(f): |
1512 if f[0] == "/": continue |
1528 continue |
|
1529 if f[0] == "/": |
|
1530 continue |
1513 if f in ma and n != ma[f]: |
1531 if f in ma and n != ma[f]: |
1514 r = _("k") |
1532 r = _("k") |
1515 if not force and (linear_path or allow): |
1533 if not force and (linear_path or allow): |
1516 r = self.ui.prompt( |
1534 r = self.ui.prompt( |
1517 (_("remote changed %s which local deleted\n") % f) + |
1535 (_("remote changed %s which local deleted\n") % f) + |
1518 _("(k)eep or (d)elete?"), _("[kd]"), _("k")) |
1536 _("(k)eep or (d)elete?"), _("[kd]"), _("k")) |
1519 if r == _("k"): get[f] = n |
1537 if r == _("k"): |
|
1538 get[f] = n |
1520 elif f not in ma: |
1539 elif f not in ma: |
1521 self.ui.debug(_("remote created %s\n") % f) |
1540 self.ui.debug(_("remote created %s\n") % f) |
1522 get[f] = n |
1541 get[f] = n |
1523 else: |
1542 else: |
1524 if force or p2 == pa: # going backwards? |
1543 if force or p2 == pa: # going backwards? |
1544 " affecting the following files:\n")) |
1563 " affecting the following files:\n")) |
1545 fl = merge.keys() + get.keys() |
1564 fl = merge.keys() + get.keys() |
1546 fl.sort() |
1565 fl.sort() |
1547 for f in fl: |
1566 for f in fl: |
1548 cf = "" |
1567 cf = "" |
1549 if f in merge: cf = _(" (resolve)") |
1568 if f in merge: |
|
1569 cf = _(" (resolve)") |
1550 self.ui.status(" %s%s\n" % (f, cf)) |
1570 self.ui.status(" %s%s\n" % (f, cf)) |
1551 self.ui.warn(_("aborting update spanning branches!\n")) |
1571 self.ui.warn(_("aborting update spanning branches!\n")) |
1552 self.ui.status(_("(use update -m to merge across branches" |
1572 self.ui.status(_("(use update -m to merge across branches" |
1553 " or -C to lose changes)\n")) |
1573 " or -C to lose changes)\n")) |
1554 return 1 |
1574 return 1 |
1719 for f, fn in ff: |
1740 for f, fn in ff: |
1720 filenodes.setdefault(f, {})[bin(fn[:40])] = 1 |
1741 filenodes.setdefault(f, {})[bin(fn[:40])] = 1 |
1721 |
1742 |
1722 self.ui.status(_("crosschecking files in changesets and manifests\n")) |
1743 self.ui.status(_("crosschecking files in changesets and manifests\n")) |
1723 |
1744 |
1724 for m,c in neededmanifests.items(): |
1745 for m, c in neededmanifests.items(): |
1725 err(_("Changeset %s refers to unknown manifest %s") % |
1746 err(_("Changeset %s refers to unknown manifest %s") % |
1726 (short(m), short(c))) |
1747 (short(m), short(c))) |
1727 del neededmanifests |
1748 del neededmanifests |
1728 |
1749 |
1729 for f in filenodes: |
1750 for f in filenodes: |
1736 |
1757 |
1737 self.ui.status(_("checking files\n")) |
1758 self.ui.status(_("checking files\n")) |
1738 ff = filenodes.keys() |
1759 ff = filenodes.keys() |
1739 ff.sort() |
1760 ff.sort() |
1740 for f in ff: |
1761 for f in ff: |
1741 if f == "/dev/null": continue |
1762 if f == "/dev/null": |
|
1763 continue |
1742 files += 1 |
1764 files += 1 |
1743 fl = self.file(f) |
1765 fl = self.file(f) |
1744 d = fl.checksize() |
1766 d = fl.checksize() |
1745 if d: |
1767 if d: |
1746 err(_("%s file data short %d bytes") % (f, d)) |
1768 err(_("%s file data short %d bytes") % (f, d)) |
1747 |
1769 |
1748 nodes = { nullid: 1 } |
1770 nodes = {nullid: 1} |
1749 seen = {} |
1771 seen = {} |
1750 for i in range(fl.count()): |
1772 for i in range(fl.count()): |
1751 revisions += 1 |
1773 revisions += 1 |
1752 n = fl.node(i) |
1774 n = fl.node(i) |
1753 |
1775 |