views.actions: Fix action dialog when revprompt is true and argprompt is false
[git-cola.git] / cola / main.py
blob522e3b9d1fe399bb1382303196dc5452e74dc32d
1 # Copyright (C) 2009, David Aguilar <davvid@gmail.com>
2 """Provides the main() routine used by the git-cola script"""
4 import optparse
5 import signal
6 import glob
7 import sys
8 import os
10 import cola
11 from cola import resources
12 from cola import utils
13 from cola import core
14 from cola import git
15 from cola import inotify
16 from cola import version
17 from cola import signals
19 # Spoof an X11 display for SSH
20 os.environ.setdefault('DISPLAY', ':0')
22 # Provide an SSH_ASKPASS fallback
23 if sys.platform == 'darwin':
24 os.environ.setdefault('SSH_ASKPASS',
25 resources.share('bin', 'ssh-askpass-darwin'))
26 else:
27 os.environ.setdefault('SSH_ASKPASS',
28 resources.share('bin', 'ssh-askpass'))
31 def main():
32 """Parses the command-line arguments and starts git-cola
33 """
34 parser = optparse.OptionParser(usage='%prog [options]')
36 # We also accept 'git cola version'
37 parser.add_option('-v', '--version',
38 help='Show cola version',
39 dest='version',
40 default=False,
41 action='store_true')
43 # Accept git cola --classic
44 parser.add_option('--classic',
45 help='Launch cola classic',
46 dest='classic',
47 default=False,
48 action='store_true')
50 # Accept --style=/path/to/style.qss or --style=dark for built-in styles
51 parser.add_option('-s', '--style',
52 help='Applies an alternate stylesheet. '
53 'The allowed values are: "dark" or a file path.',
54 dest='style',
55 metavar='PATH or STYLE',
56 default='')
58 # Specifies a git repository to open
59 parser.add_option('-r', '--repo',
60 help='Specifies the path to a git repository.',
61 dest='repo',
62 metavar='PATH',
63 default=os.getcwd())
65 # Used on Windows for adding 'git' to the path
66 parser.add_option('-g', '--git-path',
67 help='Specifies the path to the git binary',
68 dest='git',
69 metavar='PATH',
70 default='')
71 opts, args = parser.parse_args()
73 if opts.version or (args and args[0] == 'version'):
74 # Accept 'git cola --version' or 'git cola version'
75 print 'cola version', version.version()
76 sys.exit(0)
78 if opts.git:
79 # Adds git to the PATH. This is needed on Windows.
80 path_entries = os.environ.get('PATH', '').split(os.pathsep)
81 path_entries.insert(0, os.path.dirname(opts.git))
82 os.environ['PATH'] = os.pathsep.join(path_entries)
84 # Bail out if --repo is not a directory
85 repo = os.path.realpath(opts.repo)
86 if not os.path.isdir(repo):
87 print >> sys.stderr, "fatal: '%s' is not a directory. Consider supplying -r <path>.\n" % repo
88 sys.exit(-1)
90 # We do everything relative to the repo root
91 os.chdir(opts.repo)
93 try:
94 # Defer these imports to allow git cola --version without pyqt installed
95 from PyQt4 import QtCore
96 from PyQt4 import QtGui
97 except ImportError:
98 print >> sys.stderr, 'Sorry, you do not seem to have PyQt4 installed.'
99 print >> sys.stderr, 'Please install it before using cola.'
100 print >> sys.stderr, 'e.g.: sudo apt-get install python-qt4'
101 sys.exit(-1)
103 # Import cola modules
104 import cola
105 from cola.models.gitrepo import GitRepoModel
106 from cola.views import startup
107 from cola.views.main import MainView
108 from cola.views.repo import RepoDialog
109 from cola.controllers.main import MainController
110 from cola.controllers.classic import cola_classic
111 from cola.app import ColaApplication
112 from cola import qtutils
113 from cola import commands
116 # Allow Ctrl-C to exit
117 signal.signal(signal.SIGINT, signal.SIG_DFL)
119 # Initialize the app
120 app = ColaApplication(sys.argv)
122 style = None
123 if opts.style:
124 # This loads the built-in and user-specified stylesheets.
125 # We allows absolute and relative paths to a stylesheet
126 # by assuming that non-file arguments refer to a built-in style.
127 if os.path.isabs(opts.style) or os.path.isfile(opts.style):
128 filename = opts.style
129 else:
130 filename = resources.stylesheet(opts.style)
132 if filename and os.path.exists(filename):
133 # Automatically register each subdirectory in the style dir
134 # as a Qt resource directory.
135 _setup_resource_dir(os.path.dirname(filename))
136 stylesheet = open(filename, 'r')
137 style = core.read_nointr(stylesheet)
138 stylesheet.close()
139 app.setStyleSheet(style)
140 else:
141 _setup_resource_dir(resources.style_dir())
142 print >> sys.stderr, ("warn: '%s' is not a valid style."
143 % opts.style)
144 else:
145 # Add the default style dir so that we find our icons
146 _setup_resource_dir(resources.style_dir())
148 # Register model commands
149 commands.register()
151 # Ensure that we're working in a valid git repository.
152 # If not, try to find one. When found, chdir there.
153 model = cola.model()
154 valid = model.use_worktree(repo)
155 while not valid:
156 startup_dlg = startup.StartupDialog(app.activeWindow())
157 gitdir = startup_dlg.find_git_repo()
158 if not gitdir:
159 sys.exit(-1)
160 valid = model.use_worktree(gitdir)
162 # Finally, go to the root of the git repo
163 os.chdir(model.git.worktree())
165 # Show the GUI and start the event loop
166 if opts.classic:
167 view = cola_classic(update=False)
168 else:
169 view = MainView()
170 MainController(model, view)
172 # Scan for the first time
173 model.update_status()
175 # Start the inotify thread
176 inotify.start()
178 # Make sure that we start out on top
179 view.raise_()
181 # Show the view and start the main event loop
182 view.show()
183 git.GIT_COLA_TRACE = os.getenv('GIT_COLA_TRACE', False)
184 if git.GIT_COLA_TRACE:
185 msg = ('info: Trace enabled. '
186 'Many of commands reported with "trace" use git\'s stable '
187 '"plumbing" API and are not intended for typical '
188 'day-to-day use. Here be dragons')
189 cola.notifier().broadcast(signals.log_cmd, 0, msg)
190 result = app.exec_()
192 # All done, cleanup
193 inotify.stop()
195 # TODO: Provide fallback implementation
196 if hasattr(QtCore, 'QThreadPool'):
197 QtCore.QThreadPool.globalInstance().waitForDone()
199 pattern = cola.model().tmp_file_pattern()
200 for filename in glob.glob(pattern):
201 os.unlink(filename)
202 sys.exit(result)
205 def _setup_resource_dir(dirname):
206 """Adds resource directories to Qt's search path"""
207 from PyQt4 import QtCore
208 resource_paths = resources.resource_dirs(dirname)
209 for r in resource_paths:
210 basename = os.path.basename(r)
211 QtCore.QDir.setSearchPaths(basename, [r])