15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#!/usr/bin/env python
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# Copyright (c) 2011 The Chromium Authors. All rights reserved.
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# Use of this source code is governed by a BSD-style license that can be
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# found in the LICENSE file.
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)"""Usage: <win-path-to-pdb.pdb>
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)This tool will take a PDB on the command line, extract the source files that
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)were used in building the PDB, query SVN for which repository and revision
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)these files are at, and then finally write this information back into the PDB
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)in a format that the debugging tools understand.  This allows for automatic
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)source debugging, as all of the information is contained in the PDB, and the
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)debugger can go out and fetch the source files via SVN.
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)You most likely want to run these immediately after a build, since the source
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)input files need to match the generated PDB, and we want the correct SVN
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)revision information for the exact files that were used for the build.
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)The following files from a windbg + source server installation are expected
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)to reside in the same directory as this python script:
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dbghelp.dll
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pdbstr.exe
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  srctool.exe
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)NOTE: Expected to run under a native win32 python, NOT cygwin.  All paths are
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)dealt with as win32 paths, since we have to interact with the Microsoft tools.
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)"""
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import sys
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import os
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import time
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import subprocess
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import tempfile
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# This serves two purposes.  First, it acts as a whitelist, and only files
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# from repositories listed here will be source indexed.  Second, it allows us
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# to map from one SVN URL to another, so we can map to external SVN servers.
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)REPO_MAP = {
38c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  "svn://chrome-svn/blink": "http://src.chromium.org/blink",
39c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  "svn://chrome-svn/chrome": "http://src.chromium.org/chrome",
40c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  "svn://chrome-svn/multivm": "http://src.chromium.org/multivm",
41c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  "svn://chrome-svn/native_client": "http://src.chromium.org/native_client",
42c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  "svn://chrome-svn.corp.google.com/blink": "http://src.chromium.org/blink",
43c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  "svn://chrome-svn.corp.google.com/chrome": "http://src.chromium.org/chrome",
44c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  "svn://chrome-svn.corp.google.com/multivm": "http://src.chromium.org/multivm",
45c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  "svn://chrome-svn.corp.google.com/native_client":
46c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      "http://src.chromium.org/native_client",
47c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  "svn://svn-mirror.golo.chromium.org/blink": "http://src.chromium.org/blink",
48c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  "svn://svn-mirror.golo.chromium.org/chrome": "http://src.chromium.org/chrome",
49c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  "svn://svn-mirror.golo.chromium.org/multivm":
50c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      "http://src.chromium.org/multivm",
51c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  "svn://svn-mirror.golo.chromium.org/native_client":
52c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      "http://src.chromium.org/native_client",
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  "http://v8.googlecode.com/svn": None,
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  "http://google-breakpad.googlecode.com/svn": None,
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  "http://googletest.googlecode.com/svn": None,
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  "http://open-vcdiff.googlecode.com/svn": None,
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  "http://google-url.googlecode.com/svn": None,
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def FindFile(filename):
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  """Return the full windows path to a file in the same dir as this code."""
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  thisdir = os.path.dirname(os.path.join(os.path.curdir, __file__))
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return os.path.abspath(os.path.join(thisdir, filename))
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def ExtractSourceFiles(pdb_filename):
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  """Extract a list of local paths of the source files from a PDB."""
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  srctool = subprocess.Popen([FindFile('srctool.exe'), '-r', pdb_filename],
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             stdout=subprocess.PIPE, stderr=subprocess.PIPE)
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  filelist = srctool.stdout.read()
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  res = srctool.wait()
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if res != 0 or filelist.startswith("srctool: "):
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    raise "srctool failed: " + filelist
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return [x for x in filelist.split('\r\n') if len(x) != 0]
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def ReadSourceStream(pdb_filename):
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  """Read the contents of the source information stream from a PDB."""
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  srctool = subprocess.Popen([FindFile('pdbstr.exe'),
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              '-r', '-s:srcsrv',
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              '-p:%s' % pdb_filename],
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             stdout=subprocess.PIPE, stderr=subprocess.PIPE)
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data = srctool.stdout.read()
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  res = srctool.wait()
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (res != 0 and res != -1) or data.startswith("pdbstr: "):
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    raise "pdbstr failed: " + data
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return data
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def WriteSourceStream(pdb_filename, data):
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  """Write the contents of the source information stream to a PDB."""
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  # Write out the data to a temporary filename that we can pass to pdbstr.
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  (f, fname) = tempfile.mkstemp()
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  f = os.fdopen(f, "wb")
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  f.write(data)
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  f.close()
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  srctool = subprocess.Popen([FindFile('pdbstr.exe'),
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              '-w', '-s:srcsrv',
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              '-i:%s' % fname,
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              '-p:%s' % pdb_filename],
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             stdout=subprocess.PIPE, stderr=subprocess.PIPE)
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data = srctool.stdout.read()
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  res = srctool.wait()
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (res != 0 and res != -1) or data.startswith("pdbstr: "):
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    raise "pdbstr failed: " + data
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  os.unlink(fname)
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# TODO for performance, we should probably work in directories instead of
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# files.  I'm scared of DEPS and generated files, so for now we query each
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# individual file, and don't make assumptions that all files in the same
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# directory are part of the same repository or at the same revision number.
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def ExtractSvnInfo(local_filename):
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  """Calls svn info to extract the repository, path, and revision."""
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  # We call svn.bat to make sure and get the depot tools SVN and not cygwin.
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  srctool = subprocess.Popen(['svn.bat', 'info', local_filename],
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             stdout=subprocess.PIPE, stderr=subprocess.PIPE)
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  info = srctool.stdout.read()
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  res = srctool.wait()
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if res != 0:
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return None
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  # Hack up into a dictionary of the fields printed by svn info.
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  vals = dict((y.split(': ', 2) for y in info.split('\r\n') if y))
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  root = vals['Repository Root']
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if not vals['URL'].startswith(root):
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    raise "URL is not inside of the repository root?!?"
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  path = vals['URL'][len(root):]
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rev  = int(vals['Revision'])
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return [root, path, rev]
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def UpdatePDB(pdb_filename, verbose=False):
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  """Update a pdb file with source information."""
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dir_blacklist = { }
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  # TODO(deanm) look into "compressing" our output, by making use of vars
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  # and other things, so we don't need to duplicate the repo path and revs.
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  lines = [
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    'SRCSRV: ini ------------------------------------------------',
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    'VERSION=1',
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    'INDEXVERSION=2',
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    'VERCTRL=Subversion',
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    'DATETIME=%s' % time.asctime(),
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    'SRCSRV: variables ------------------------------------------',
1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    'SVN_EXTRACT_TARGET_DIR=%targ%\%fnbksl%(%var3%)\%var4%',
1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    'SVN_EXTRACT_TARGET=%svn_extract_target_dir%\%fnfile%(%var1%)',
1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    'SVN_EXTRACT_CMD=cmd /c mkdir "%svn_extract_target_dir%" && cmd /c svn cat "%var2%%var3%@%var4%" --non-interactive > "%svn_extract_target%"',
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    'SRCSRVTRG=%SVN_extract_target%',
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    'SRCSRVCMD=%SVN_extract_cmd%',
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    'SRCSRV: source files ---------------------------------------',
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ]
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if ReadSourceStream(pdb_filename):
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    raise "PDB already has source indexing information!"
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  filelist = ExtractSourceFiles(pdb_filename)
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for filename in filelist:
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    filedir = os.path.dirname(filename)
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if verbose:
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      print "Processing: %s" % filename
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # This directory is blacklisted, either because it's not part of the SVN
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # repository, or from one we're not interested in indexing.
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if dir_blacklist.get(filedir, False):
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if verbose:
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        print "  skipping, directory is blacklisted."
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    info = ExtractSvnInfo(filename)
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # Skip the file if it's not under an svn repository.  To avoid constantly
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # querying SVN for files outside of SVN control (for example, the CRT
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # sources), check if the directory is outside of SVN and blacklist it.
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if not info:
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if not ExtractSvnInfo(filedir):
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        dir_blacklist[filedir] = True
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if verbose:
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        print "  skipping, file is not in an SVN repository"
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    root = info[0]
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    path = info[1]
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rev  = info[2]
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # Check if file was from a svn repository we don't know about, or don't
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # want to index.  Blacklist the entire directory.
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if not REPO_MAP.has_key(info[0]):
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if verbose:
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        print "  skipping, file is from an unknown SVN repository %s" % root
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      dir_blacklist[filedir] = True
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # We might want to map an internal repository URL to an external repository.
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if REPO_MAP[root]:
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      root = REPO_MAP[root]
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    lines.append('%s*%s*%s*%s' % (filename, root, path, rev))
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if verbose:
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      print "  indexed file."
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  lines.append('SRCSRV: end ------------------------------------------------')
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WriteSourceStream(pdb_filename, '\r\n'.join(lines))
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def main():
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if len(sys.argv) < 2 or len(sys.argv) > 3:
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    print "usage: file.pdb [-v]"
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return 1
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  verbose = False
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if len(sys.argv) == 3:
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    verbose = (sys.argv[2] == '-v')
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UpdatePDB(sys.argv[1], verbose=verbose)
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return 0
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)if __name__ == '__main__':
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sys.exit(main())
227