1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191
|
# -*- coding: utf-8 -*-
# Copyright (c) 2003-2011 LOGILAB S.A. (Paris, FRANCE).
# http://www.logilab.fr/ -- mailto:contact@logilab.fr
#
# This program is free software; you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free Software
# Foundation; either version 2 of the License, or (at your option) any later
# version.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along with
# this program. If not, see <http://www.gnu.org/licenses/>.
"""
Application utilities.
"""
import os, sys
from optparse import OptionParser
from mercurial import hg, ui
from mercurial.error import RepoError
from hgviewlib.util import find_repository, rootpath
from hgviewlib.config import HgConfig
class Viewer(object):
"""Base viewer class interface."""
def __init__(self, *args, **kwargs):
raise NotImplementedError(
'This feature has not yet been implemented. Comming soon ...')
class FileViewer(Viewer):
"""Single file revision graph viewer."""
def __init__(self, repo, filename, **kwargs):
super(FileDiffViewer, self).__init__(**kwargs)
class FileDiffViewer(Viewer):
"""Viewer that displays diffs between different revisions of a file."""
def __init__(self, repo, filename, **kwargs):
super(FileDiffViewer, self).__init__(**kwargs)
class HgRepoViewer(Viewer):
"""hg repository viewer."""
def __init__(self, repo, **kwargs):
super(HgRepoViewer, self).__init__(**kwargs)
class ManifestViewer(Viewer):
"""Viewer that displays all files of a repo at a given revision"""
def __init__(self, repo, rev, **kwargs):
super(ManifestViewer, self).__init__(**kwargs)
class ApplicationError(ValueError):
"""Exception that may occures while lunching the application"""
class HgViewApplication(object):
# class that must be instancied
FileViewer = FileViewer
FileDiffViewer = FileDiffViewer
HgRepoViewer = HgRepoViewer
ManifestViewer = ManifestViewer
def __init__(self, repo, opts, args, **kawrgs):
self.viewer = None
if opts.navigate and len(args) != 1:
ApplicationError(
"you must provide a filename to start in navigate mode")
if len(args) > 1:
ApplicationError("provide at most one file name")
self.opts = opts
self.args = args
self.repo = repo
self.choose_viewer()
def choose_viewer(self):
"""Choose the right viewer"""
if len(self.args) == 1:
filename = rootpath(self.repo, self.opts.rev, self.args[0])
if not filename:
raise ApplicationError("%s is not a tracked file" % self.args[0])
# should be a filename of a file managed in the repo
if self.opts.navigate:
viewer = self.FileViewer(self.repo, filename)
else:
viewer = self.FileDiffViewer(self.repo, filename)
else:
rev = self.opts.rev
if rev:
try:
self.repo.changectx(rev)
except RepoError, e:
raise ApplicationError("Cannot find revision %s" % rev)
else:
viewer = self.ManifestViewer(self.repo, rev)
else:
viewer = self.HgRepoViewer(self.repo)
self.viewer = viewer
def exec_(self):
raise NotImplementedError()
def start(repo, opts, args, fnerror):
"""
start hgview
"""
config = HgConfig(repo.ui)
if not opts.interface:
opts.interface = config.getInterface()
Application = None
if not opts.interface or opts.interface == 'qt':
try:
from hgviewlib.qt4.application import HgViewQtApplication as Application
opts.interface = 'qt'
except ImportError:
pass
if not opts.interface or opts.interface in ('raw', 'curses'):
try:
from hgviewlib.curses.application import HgViewUrwidApplication as Application
opts.interface = 'raw'
except ImportError:
pass
if not opts.interface:
fnerror('No interface found')
if not Application:
fnerror('Interface is not available: %s' % opts.interface)
try:
app = Application(repo, opts, args)
except (ApplicationError, NotImplementedError), err:
fnerror(str(err))
return app.exec_()
def main():
"""
Main application acces point.
"""
usage = '''%prog [options] [filename]
Starts a visual hg repository navigator.
- With no options, starts the main repository navigator.
- If a filename is given, starts in filelog diff mode (or in
filelog navigation mode if -n option is set).
- With -r option, starts in manifest viewer mode for given
revision.
'''
parser = OptionParser(usage)
parser.add_option('-I', '--interface', dest='interface',
help=('which GUI interface to use (among "qt", "raw"'
' and "curses")'),
)
parser.add_option('-R', '--repository', dest='repo',
help='location of the repository to explore')
parser.add_option('-r', '--rev', dest='rev', default=None,
help='start in manifest navigation mode at rev R')
parser.add_option('-n', '--navigate', dest='navigate', default=False,
action="store_true",
help='(with filename) start in navigation mode')
opts, args = parser.parse_args()
if opts.repo:
dir_ = opts.repo
else:
dir_ = os.getcwd()
dir_ = find_repository(dir_)
try:
u = ui.ui()
repo = hg.repository(u, dir_)
except RepoError, e:
parser.error(e)
except:
parser.error("There is no Mercurial repository here (.hg not found)!")
try:
sys.exit(start(repo, opts, args, parser.error))
except KeyboardInterrupt:
print 'interrupted!'
|