test/tmp: Add .gitignore so that this directory always exists
[git-cola.git] / cola / main.py
blob31cbaf18006e0cf1495d3917ec20a00bfa19d49b
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 import qtcompat
106 qtcompat.install()
108 from cola.models.gitrepo import GitRepoModel
109 from cola.views import startup
110 from cola.views.main import MainView
111 from cola.views.repo import RepoDialog
112 from cola.controllers.main import MainController
113 from cola.controllers.classic import cola_classic
114 from cola.app import ColaApplication
115 from cola import qtutils
116 from cola import cmds
119 # Allow Ctrl-C to exit
120 signal.signal(signal.SIGINT, signal.SIG_DFL)
122 # Initialize the app
123 app = ColaApplication(sys.argv)
125 style = None
126 if opts.style:
127 # This loads the built-in and user-specified stylesheets.
128 # We allows absolute and relative paths to a stylesheet
129 # by assuming that non-file arguments refer to a built-in style.
130 if os.path.isabs(opts.style) or os.path.isfile(opts.style):
131 filename = opts.style
132 else:
133 filename = resources.stylesheet(opts.style)
135 if filename and os.path.exists(filename):
136 # Automatically register each subdirectory in the style dir
137 # as a Qt resource directory.
138 _setup_resource_dir(os.path.dirname(filename))
139 stylesheet = open(filename, 'r')
140 style = core.read_nointr(stylesheet)
141 stylesheet.close()
142 app.setStyleSheet(style)
143 else:
144 _setup_resource_dir(resources.style_dir())
145 print >> sys.stderr, ("warn: '%s' is not a valid style."
146 % opts.style)
147 else:
148 # Add the default style dir so that we find our icons
149 _setup_resource_dir(resources.style_dir())
151 # Register model commands
152 cmds.register()
154 # Ensure that we're working in a valid git repository.
155 # If not, try to find one. When found, chdir there.
156 model = cola.model()
157 valid = model.use_worktree(repo)
158 while not valid:
159 startup_dlg = startup.StartupDialog(app.activeWindow())
160 gitdir = startup_dlg.find_git_repo()
161 if not gitdir:
162 sys.exit(-1)
163 valid = model.use_worktree(gitdir)
165 # Finally, go to the root of the git repo
166 os.chdir(model.git.worktree())
168 # Show the GUI and start the event loop
169 if opts.classic:
170 view = cola_classic(update=False)
171 else:
172 view = MainView()
173 MainController(model, view)
175 # Scan for the first time
176 model.update_status()
178 # Start the inotify thread
179 inotify.start()
181 # Make sure that we start out on top
182 view.raise_()
184 # Show the view and start the main event loop
185 view.show()
186 git.GIT_COLA_TRACE = os.getenv('GIT_COLA_TRACE', False)
187 if git.GIT_COLA_TRACE:
188 msg = ('info: Trace enabled. '
189 'Many of commands reported with "trace" use git\'s stable '
190 '"plumbing" API and are not intended for typical '
191 'day-to-day use. Here be dragons')
192 cola.notifier().broadcast(signals.log_cmd, 0, msg)
193 result = app.exec_()
195 # All done, cleanup
196 inotify.stop()
198 # TODO: Provide fallback implementation
199 if hasattr(QtCore, 'QThreadPool'):
200 QtCore.QThreadPool.globalInstance().waitForDone()
202 pattern = cola.model().tmp_file_pattern()
203 for filename in glob.glob(pattern):
204 os.unlink(filename)
205 sys.exit(result)
208 def _setup_resource_dir(dirname):
209 """Adds resource directories to Qt's search path"""
210 from cola import qtcompat
212 resource_paths = resources.resource_dirs(dirname)
213 for r in resource_paths:
214 basename = os.path.basename(r)
215 qtcompat.add_search_path(basename, r)