hgext/git/index.py
author Matt Harbison <matt_harbison@yahoo.com>
Tue, 27 Apr 2021 18:39:59 -0400
branchstable
changeset 47051 de26b9a7ec29
parent 46113 59fa3890d40a
child 47057 7431f5ab0d2a
permissions -rw-r--r--
git: consistently use str for parents when rebuilding the index database The tests show no changes, but when these values are overwritten shortly after when a git commit object is available, that uses str. It seems better to use that for consistency. It does materially affect the database though, because the old value stored was `X'3030..3030'` and is now '00..00' when the changelog table is dumped in sqlite3. There is one query that specifies the parents, but it passes the non null hashes as str, so it worked as expected. That likely explains the lack of test changes. Differential Revision: https://phab.mercurial-scm.org/D10527
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
44477
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
     1
from __future__ import absolute_import
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
     2
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
     3
import collections
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
     4
import os
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
     5
import sqlite3
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
     6
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
     7
from mercurial.i18n import _
46113
59fa3890d40a node: import symbols explicitly
Joerg Sonnenberger <joerg@bec.de>
parents: 44951
diff changeset
     8
from mercurial.node import (
59fa3890d40a node: import symbols explicitly
Joerg Sonnenberger <joerg@bec.de>
parents: 44951
diff changeset
     9
    nullid,
59fa3890d40a node: import symbols explicitly
Joerg Sonnenberger <joerg@bec.de>
parents: 44951
diff changeset
    10
)
44477
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    11
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    12
from mercurial import (
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    13
    encoding,
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    14
    error,
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    15
    pycompat,
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    16
)
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    17
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    18
from . import gitutil
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    19
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    20
44484
ec54b3d2af0b git: don't fail import when pygit2 is not install
Martin von Zweigbergk <martinvonz@google.com>
parents: 44477
diff changeset
    21
pygit2 = gitutil.get_pygit2()
ec54b3d2af0b git: don't fail import when pygit2 is not install
Martin von Zweigbergk <martinvonz@google.com>
parents: 44477
diff changeset
    22
44477
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    23
_CURRENT_SCHEMA_VERSION = 1
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    24
_SCHEMA = (
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    25
    """
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    26
CREATE TABLE refs (
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    27
  -- node and name are unique together. There may be more than one name for
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    28
  -- a given node, and there may be no name at all for a given node (in the
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    29
  -- case of an anonymous hg head).
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    30
  node TEXT NOT NULL,
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    31
  name TEXT
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    32
);
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    33
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    34
-- The "possible heads" of the repository, which we use to figure out
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    35
-- if we need to re-walk the changelog.
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    36
CREATE TABLE possible_heads (
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    37
  node TEXT NOT NULL
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    38
);
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    39
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    40
-- The topological heads of the changelog, which hg depends on.
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    41
CREATE TABLE heads (
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    42
  node TEXT NOT NULL
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    43
);
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    44
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    45
-- A total ordering of the changelog
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    46
CREATE TABLE changelog (
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    47
  rev INTEGER NOT NULL PRIMARY KEY,
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    48
  node TEXT NOT NULL,
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    49
  p1 TEXT,
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    50
  p2 TEXT
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    51
);
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    52
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    53
CREATE UNIQUE INDEX changelog_node_idx ON changelog(node);
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    54
CREATE UNIQUE INDEX changelog_node_rev_idx ON changelog(rev, node);
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    55
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    56
-- Changed files for each commit, which lets us dynamically build
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    57
-- filelogs.
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    58
CREATE TABLE changedfiles (
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    59
  node TEXT NOT NULL,
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    60
  filename TEXT NOT NULL,
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    61
  -- 40 zeroes for deletions
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    62
  filenode TEXT NOT NULL,
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    63
-- to handle filelog parentage:
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    64
  p1node TEXT,
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    65
  p1filenode TEXT,
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    66
  p2node TEXT,
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    67
  p2filenode TEXT
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    68
);
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    69
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    70
CREATE INDEX changedfiles_nodes_idx
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    71
  ON changedfiles(node);
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    72
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    73
PRAGMA user_version=%d
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    74
"""
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    75
    % _CURRENT_SCHEMA_VERSION
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    76
)
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    77
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    78
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    79
def _createdb(path):
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    80
    # print('open db', path)
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    81
    # import traceback
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    82
    # traceback.print_stack()
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    83
    db = sqlite3.connect(encoding.strfromlocal(path))
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    84
    db.text_factory = bytes
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    85
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    86
    res = db.execute('PRAGMA user_version').fetchone()[0]
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    87
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    88
    # New database.
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    89
    if res == 0:
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    90
        for statement in _SCHEMA.split(';'):
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    91
            db.execute(statement.strip())
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    92
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    93
        db.commit()
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    94
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    95
    elif res == _CURRENT_SCHEMA_VERSION:
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    96
        pass
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    97
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    98
    else:
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    99
        raise error.Abort(_(b'sqlite database has unrecognized version'))
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   100
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   101
    db.execute('PRAGMA journal_mode=WAL')
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   102
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   103
    return db
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   104
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   105
44484
ec54b3d2af0b git: don't fail import when pygit2 is not install
Martin von Zweigbergk <martinvonz@google.com>
parents: 44477
diff changeset
   106
_OUR_ORDER = ()
ec54b3d2af0b git: don't fail import when pygit2 is not install
Martin von Zweigbergk <martinvonz@google.com>
parents: 44477
diff changeset
   107
if pygit2:
ec54b3d2af0b git: don't fail import when pygit2 is not install
Martin von Zweigbergk <martinvonz@google.com>
parents: 44477
diff changeset
   108
    _OUR_ORDER = (
ec54b3d2af0b git: don't fail import when pygit2 is not install
Martin von Zweigbergk <martinvonz@google.com>
parents: 44477
diff changeset
   109
        pygit2.GIT_SORT_TOPOLOGICAL
ec54b3d2af0b git: don't fail import when pygit2 is not install
Martin von Zweigbergk <martinvonz@google.com>
parents: 44477
diff changeset
   110
        | pygit2.GIT_SORT_TIME
ec54b3d2af0b git: don't fail import when pygit2 is not install
Martin von Zweigbergk <martinvonz@google.com>
parents: 44477
diff changeset
   111
        | pygit2.GIT_SORT_REVERSE
ec54b3d2af0b git: don't fail import when pygit2 is not install
Martin von Zweigbergk <martinvonz@google.com>
parents: 44477
diff changeset
   112
    )
44477
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   113
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   114
_DIFF_FLAGS = 1 << 21  # GIT_DIFF_FORCE_BINARY, which isn't exposed by pygit2
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   115
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   116
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   117
def _find_nearest_ancestor_introducing_node(
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   118
    db, gitrepo, file_path, walk_start, filenode
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   119
):
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   120
    """Find the nearest ancestor that introduces a file node.
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   121
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   122
    Args:
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   123
      db: a handle to our sqlite database.
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   124
      gitrepo: A pygit2.Repository instance.
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   125
      file_path: the path of a file in the repo
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   126
      walk_start: a pygit2.Oid that is a commit where we should start walking
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   127
                  for our nearest ancestor.
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   128
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   129
    Returns:
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   130
      A hexlified SHA that is the commit ID of the next-nearest parent.
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   131
    """
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   132
    assert isinstance(file_path, str), 'file_path must be str, got %r' % type(
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   133
        file_path
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   134
    )
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   135
    assert isinstance(filenode, str), 'filenode must be str, got %r' % type(
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   136
        filenode
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   137
    )
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   138
    parent_options = {
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   139
        row[0].decode('ascii')
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   140
        for row in db.execute(
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   141
            'SELECT node FROM changedfiles '
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   142
            'WHERE filename = ? AND filenode = ?',
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   143
            (file_path, filenode),
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   144
        )
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   145
    }
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   146
    inner_walker = gitrepo.walk(walk_start, _OUR_ORDER)
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   147
    for w in inner_walker:
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   148
        if w.id.hex in parent_options:
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   149
            return w.id.hex
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   150
    raise error.ProgrammingError(
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   151
        'Unable to find introducing commit for %s node %s from %s',
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   152
        (file_path, filenode, walk_start),
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   153
    )
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   154
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   155
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   156
def fill_in_filelog(gitrepo, db, startcommit, path, startfilenode):
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   157
    """Given a starting commit and path, fill in a filelog's parent pointers.
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   158
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   159
    Args:
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   160
      gitrepo: a pygit2.Repository
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   161
      db: a handle to our sqlite database
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   162
      startcommit: a hexlified node id for the commit to start at
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   163
      path: the path of the file whose parent pointers we should fill in.
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   164
      filenode: the hexlified node id of the file at startcommit
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   165
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   166
    TODO: make filenode optional
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   167
    """
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   168
    assert isinstance(
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   169
        startcommit, str
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   170
    ), 'startcommit must be str, got %r' % type(startcommit)
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   171
    assert isinstance(
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   172
        startfilenode, str
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   173
    ), 'startfilenode must be str, got %r' % type(startfilenode)
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   174
    visit = collections.deque([(startcommit, startfilenode)])
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   175
    while visit:
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   176
        cnode, filenode = visit.popleft()
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   177
        commit = gitrepo[cnode]
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   178
        parents = []
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   179
        for parent in commit.parents:
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   180
            t = parent.tree
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   181
            for comp in path.split('/'):
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   182
                try:
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   183
                    t = gitrepo[t[comp].id]
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   184
                except KeyError:
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   185
                    break
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   186
            else:
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   187
                introducer = _find_nearest_ancestor_introducing_node(
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   188
                    db, gitrepo, path, parent.id, t.id.hex
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   189
                )
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   190
                parents.append((introducer, t.id.hex))
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   191
        p1node = p1fnode = p2node = p2fnode = gitutil.nullgit
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   192
        for par, parfnode in parents:
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   193
            found = int(
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   194
                db.execute(
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   195
                    'SELECT COUNT(*) FROM changedfiles WHERE '
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   196
                    'node = ? AND filename = ? AND filenode = ? AND '
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   197
                    'p1node NOT NULL',
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   198
                    (par, path, parfnode),
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   199
                ).fetchone()[0]
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   200
            )
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   201
            if found == 0:
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   202
                assert par is not None
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   203
                visit.append((par, parfnode))
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   204
        if parents:
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   205
            p1node, p1fnode = parents[0]
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   206
        if len(parents) == 2:
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   207
            p2node, p2fnode = parents[1]
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   208
        if len(parents) > 2:
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   209
            raise error.ProgrammingError(
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   210
                b"git support can't handle octopus merges"
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   211
            )
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   212
        db.execute(
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   213
            'UPDATE changedfiles SET '
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   214
            'p1node = ?, p1filenode = ?, p2node = ?, p2filenode = ? '
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   215
            'WHERE node = ? AND filename = ? AND filenode = ?',
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   216
            (p1node, p1fnode, p2node, p2fnode, commit.id.hex, path, filenode),
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   217
        )
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   218
    db.commit()
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   219
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   220
44951
83e41b73d115 git: add debug logging when there's a mismatch in the cached heads list
Augie Fackler <augie@google.com>
parents: 44946
diff changeset
   221
def _index_repo(
83e41b73d115 git: add debug logging when there's a mismatch in the cached heads list
Augie Fackler <augie@google.com>
parents: 44946
diff changeset
   222
    gitrepo,
83e41b73d115 git: add debug logging when there's a mismatch in the cached heads list
Augie Fackler <augie@google.com>
parents: 44946
diff changeset
   223
    db,
83e41b73d115 git: add debug logging when there's a mismatch in the cached heads list
Augie Fackler <augie@google.com>
parents: 44946
diff changeset
   224
    logfn=lambda x: None,
83e41b73d115 git: add debug logging when there's a mismatch in the cached heads list
Augie Fackler <augie@google.com>
parents: 44946
diff changeset
   225
    progress_factory=lambda *args, **kwargs: None,
83e41b73d115 git: add debug logging when there's a mismatch in the cached heads list
Augie Fackler <augie@google.com>
parents: 44946
diff changeset
   226
):
44477
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   227
    # Identify all references so we can tell the walker to visit all of them.
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   228
    all_refs = gitrepo.listall_references()
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   229
    possible_heads = set()
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   230
    prog = progress_factory(b'refs')
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   231
    for pos, ref in enumerate(all_refs):
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   232
        if prog is not None:
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   233
            prog.update(pos)
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   234
        if not (
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   235
            ref.startswith('refs/heads/')  # local branch
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   236
            or ref.startswith('refs/tags/')  # tag
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   237
            or ref.startswith('refs/remotes/')  # remote branch
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   238
            or ref.startswith('refs/hg/')  # from this extension
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   239
        ):
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   240
            continue
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   241
        try:
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   242
            start = gitrepo.lookup_reference(ref).peel(pygit2.GIT_OBJ_COMMIT)
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   243
        except ValueError:
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   244
            # No commit to be found, so we don't care for hg's purposes.
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   245
            continue
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   246
        possible_heads.add(start.id)
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   247
    # Optimization: if the list of heads hasn't changed, don't
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   248
    # reindex, the changelog. This doesn't matter on small
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   249
    # repositories, but on even moderately deep histories (eg cpython)
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   250
    # this is a very important performance win.
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   251
    #
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   252
    # TODO: we should figure out how to incrementally index history
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   253
    # (preferably by detecting rewinds!) so that we don't have to do a
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   254
    # full changelog walk every time a new commit is created.
44946
fb2936c5f6dc git: decode node IDs back into Python strings (issue6349)
Hollis Blanchard <hollis_blanchard@mentor.com>
parents: 44484
diff changeset
   255
    cache_heads = {
fb2936c5f6dc git: decode node IDs back into Python strings (issue6349)
Hollis Blanchard <hollis_blanchard@mentor.com>
parents: 44484
diff changeset
   256
        pycompat.sysstr(x[0])
fb2936c5f6dc git: decode node IDs back into Python strings (issue6349)
Hollis Blanchard <hollis_blanchard@mentor.com>
parents: 44484
diff changeset
   257
        for x in db.execute('SELECT node FROM possible_heads')
fb2936c5f6dc git: decode node IDs back into Python strings (issue6349)
Hollis Blanchard <hollis_blanchard@mentor.com>
parents: 44484
diff changeset
   258
    }
44477
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   259
    walker = None
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   260
    cur_cache_heads = {h.hex for h in possible_heads}
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   261
    if cur_cache_heads == cache_heads:
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   262
        return
44951
83e41b73d115 git: add debug logging when there's a mismatch in the cached heads list
Augie Fackler <augie@google.com>
parents: 44946
diff changeset
   263
    logfn(b'heads mismatch, rebuilding dagcache\n')
44477
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   264
    for start in possible_heads:
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   265
        if walker is None:
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   266
            walker = gitrepo.walk(start, _OUR_ORDER)
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   267
        else:
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   268
            walker.push(start)
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   269
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   270
    # Empty out the existing changelog. Even for large-ish histories
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   271
    # we can do the top-level "walk all the commits" dance very
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   272
    # quickly as long as we don't need to figure out the changed files
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   273
    # list.
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   274
    db.execute('DELETE FROM changelog')
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   275
    if prog is not None:
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   276
        prog.complete()
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   277
    prog = progress_factory(b'commits')
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   278
    # This walker is sure to visit all the revisions in history, but
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   279
    # only once.
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   280
    for pos, commit in enumerate(walker):
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   281
        if prog is not None:
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   282
            prog.update(pos)
47051
de26b9a7ec29 git: consistently use str for parents when rebuilding the index database
Matt Harbison <matt_harbison@yahoo.com>
parents: 46113
diff changeset
   283
        p1 = p2 = gitutil.nullgit
44477
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   284
        if len(commit.parents) > 2:
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   285
            raise error.ProgrammingError(
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   286
                (
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   287
                    b"git support can't handle octopus merges, "
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   288
                    b"found a commit with %d parents :("
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   289
                )
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   290
                % len(commit.parents)
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   291
            )
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   292
        if commit.parents:
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   293
            p1 = commit.parents[0].id.hex
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   294
        if len(commit.parents) == 2:
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   295
            p2 = commit.parents[1].id.hex
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   296
        db.execute(
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   297
            'INSERT INTO changelog (rev, node, p1, p2) VALUES(?, ?, ?, ?)',
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   298
            (pos, commit.id.hex, p1, p2),
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   299
        )
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   300
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   301
        num_changedfiles = db.execute(
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   302
            "SELECT COUNT(*) from changedfiles WHERE node = ?",
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   303
            (commit.id.hex,),
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   304
        ).fetchone()[0]
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   305
        if not num_changedfiles:
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   306
            files = {}
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   307
            # I *think* we only need to check p1 for changed files
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   308
            # (and therefore linkrevs), because any node that would
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   309
            # actually have this commit as a linkrev would be
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   310
            # completely new in this rev.
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   311
            p1 = commit.parents[0].id.hex if commit.parents else None
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   312
            if p1 is not None:
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   313
                patchgen = gitrepo.diff(p1, commit.id.hex, flags=_DIFF_FLAGS)
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   314
            else:
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   315
                patchgen = commit.tree.diff_to_tree(
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   316
                    swap=True, flags=_DIFF_FLAGS
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   317
                )
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   318
            new_files = (p.delta.new_file for p in patchgen)
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   319
            files = {
46113
59fa3890d40a node: import symbols explicitly
Joerg Sonnenberger <joerg@bec.de>
parents: 44951
diff changeset
   320
                nf.path: nf.id.hex for nf in new_files if nf.id.raw != nullid
44477
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   321
            }
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   322
            for p, n in files.items():
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   323
                # We intentionally set NULLs for any file parentage
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   324
                # information so it'll get demand-computed later. We
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   325
                # used to do it right here, and it was _very_ slow.
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   326
                db.execute(
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   327
                    'INSERT INTO changedfiles ('
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   328
                    'node, filename, filenode, p1node, p1filenode, p2node, '
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   329
                    'p2filenode) VALUES(?, ?, ?, ?, ?, ?, ?)',
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   330
                    (commit.id.hex, p, n, None, None, None, None),
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   331
                )
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   332
    db.execute('DELETE FROM heads')
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   333
    db.execute('DELETE FROM possible_heads')
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   334
    for hid in possible_heads:
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   335
        h = hid.hex
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   336
        db.execute('INSERT INTO possible_heads (node) VALUES(?)', (h,))
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   337
        haschild = db.execute(
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   338
            'SELECT COUNT(*) FROM changelog WHERE p1 = ? OR p2 = ?', (h, h)
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   339
        ).fetchone()[0]
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   340
        if not haschild:
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   341
            db.execute('INSERT INTO heads (node) VALUES(?)', (h,))
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   342
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   343
    db.commit()
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   344
    if prog is not None:
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   345
        prog.complete()
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   346
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   347
44951
83e41b73d115 git: add debug logging when there's a mismatch in the cached heads list
Augie Fackler <augie@google.com>
parents: 44946
diff changeset
   348
def get_index(
83e41b73d115 git: add debug logging when there's a mismatch in the cached heads list
Augie Fackler <augie@google.com>
parents: 44946
diff changeset
   349
    gitrepo, logfn=lambda x: None, progress_factory=lambda *args, **kwargs: None
83e41b73d115 git: add debug logging when there's a mismatch in the cached heads list
Augie Fackler <augie@google.com>
parents: 44946
diff changeset
   350
):
44477
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   351
    cachepath = os.path.join(
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   352
        pycompat.fsencode(gitrepo.path), b'..', b'.hg', b'cache'
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   353
    )
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   354
    if not os.path.exists(cachepath):
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   355
        os.makedirs(cachepath)
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   356
    dbpath = os.path.join(cachepath, b'git-commits.sqlite')
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   357
    db = _createdb(dbpath)
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   358
    # TODO check against gitrepo heads before doing a full index
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   359
    # TODO thread a ui.progress call into this layer
44951
83e41b73d115 git: add debug logging when there's a mismatch in the cached heads list
Augie Fackler <augie@google.com>
parents: 44946
diff changeset
   360
    _index_repo(gitrepo, db, logfn, progress_factory)
44477
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   361
    return db