doc: Do not mention unused cola.geometry variable
[git-cola.git] / cola / main.py
blob1aa0c057ea90f122bc95fa527e5a887c90d8312b
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 from cola import resources
11 from cola import utils
12 from cola import core
13 from cola import git
14 from cola import inotify
15 from cola import version
17 # Spoof an X11 display for SSH
18 os.environ.setdefault('DISPLAY', ':0')
20 # Provide an SSH_ASKPASS fallback
21 if sys.platform == 'darwin':
22 os.environ.setdefault('SSH_ASKPASS',
23 resources.share('bin', 'ssh-askpass-darwin'))
24 else:
25 os.environ.setdefault('SSH_ASKPASS',
26 resources.share('bin', 'ssh-askpass'))
29 def main():
30 """Parses the command-line arguments and starts git-cola
31 """
32 parser = optparse.OptionParser(usage='%prog [options]')
34 # We also accept 'git cola version'
35 parser.add_option('-v', '--version',
36 help='Show cola version',
37 dest='version',
38 default=False,
39 action='store_true')
41 # Accept git cola --classic
42 parser.add_option('--classic',
43 help='Launch cola classic',
44 dest='classic',
45 default=False,
46 action='store_true')
48 # Accept --style=/path/to/style.qss or --style=dark for built-in styles
49 parser.add_option('-s', '--style',
50 help='Applies an alternate stylesheet. '
51 'The allowed values are: "dark" or a file path.',
52 dest='style',
53 metavar='PATH or STYLE',
54 default='')
56 # Specifies a git repository to open
57 parser.add_option('-r', '--repo',
58 help='Specifies the path to a git repository.',
59 dest='repo',
60 metavar='PATH',
61 default=os.getcwd())
63 # Used on Windows for adding 'git' to the path
64 parser.add_option('-g', '--git-path',
65 help='Specifies the path to the git binary',
66 dest='git',
67 metavar='PATH',
68 default='')
69 opts, args = parser.parse_args()
71 if opts.version or 'version' in args:
72 # Accept 'git cola --version' or 'git cola version'
73 git.Git.execute(['git', 'update-index', '--refresh'])
74 print 'cola version', version.version()
75 sys.exit(0)
77 if opts.git:
78 # Adds git to the PATH. This is needed on Windows.
79 path_entries = os.environ.get('PATH', '').split(os.pathsep)
80 path_entries.insert(0, os.path.dirname(opts.git))
81 os.environ['PATH'] = os.pathsep.join(path_entries)
83 # Bail out if --repo is not a directory
84 repo = os.path.realpath(opts.repo)
85 if not os.path.isdir(repo):
86 print >> sys.stderr, "fatal: '%s' is not a directory. Consider supplying -r <path>.\n" % repo
87 sys.exit(-1)
89 # We do everything relative to the repo root
90 os.chdir(opts.repo)
92 try:
93 # Defer these imports to allow git cola --version without pyqt installed
94 from PyQt4 import QtCore
95 from PyQt4 import QtGui
96 except ImportError:
97 print >> sys.stderr, 'Sorry, you do not seem to have PyQt4 installed.'
98 print >> sys.stderr, 'Please install it before using cola.'
99 print >> sys.stderr, 'e.g.: sudo apt-get install python-qt4'
100 sys.exit(-1)
102 # Import cola modules
103 import cola
104 from cola.models.gitrepo import GitRepoModel
105 from cola.views import startup
106 from cola.views.main import MainView
107 from cola.views.repo import RepoTreeView
108 from cola.controllers.main import MainController
109 from cola.controllers.classic import ClassicController
110 from cola.app import ColaApplication
111 from cola import qtutils
112 from cola import commands
115 # Allow Ctrl-C to exit
116 signal.signal(signal.SIGINT, signal.SIG_DFL)
118 # Initialize the app
119 app = ColaApplication(sys.argv)
121 style = None
122 if opts.style:
123 # This loads the built-in and user-specified stylesheets.
124 # We allows absolute and relative paths to a stylesheet
125 # by assuming that non-file arguments refer to a built-in style.
126 if os.path.isabs(opts.style) or os.path.isfile(opts.style):
127 filename = opts.style
128 else:
129 filename = resources.stylesheet(opts.style)
131 if filename and os.path.exists(filename):
132 # Automatically register each subdirectory in the style dir
133 # as a Qt resource directory.
134 _setup_resource_dir(os.path.dirname(filename))
135 stylesheet = open(filename, 'r')
136 style = core.read_nointr(stylesheet)
137 stylesheet.close()
138 app.setStyleSheet(style)
139 else:
140 _setup_resource_dir(resources.style_dir())
141 print >> sys.stderr, ("warn: '%s' is not a valid style."
142 % opts.style)
143 else:
144 # Add the default style dir so that we find our icons
145 _setup_resource_dir(resources.style_dir())
147 # Register model commands
148 commands.register()
150 # Ensure that we're working in a valid git repository.
151 # If not, try to find one. When found, chdir there.
152 model = cola.model()
153 valid = model.use_worktree(repo)
154 while not valid:
155 startup_dlg = startup.StartupDialog(app.activeWindow())
156 gitdir = startup_dlg.find_git_repo()
157 if not gitdir:
158 sys.exit(-1)
159 valid = model.use_worktree(gitdir)
161 # Finally, go to the root of the git repo
162 os.chdir(model.git.worktree())
164 # Show the GUI and start the event loop
165 if opts.classic:
166 view = RepoTreeView()
167 view.setModel(GitRepoModel(view))
168 controller = ClassicController(view)
169 else:
170 view = MainView()
171 controller = MainController(model, view)
173 # Scan for the first time
174 model.update_status()
176 # Start the inotify thread
177 inotify.start()
179 # Make sure that we start out on top
180 view.raise_()
182 # Show the view and start the main event loop
183 view.show()
184 result = app.exec_()
186 # All done, cleanup
187 inotify.stop()
189 # TODO: Provide fallback implementation
190 if hasattr(QtCore, 'QThreadPool'):
191 QtCore.QThreadPool.globalInstance().waitForDone()
193 pattern = cola.model().tmp_file_pattern()
194 for filename in glob.glob(pattern):
195 os.unlink(filename)
196 sys.exit(result)
199 def _setup_resource_dir(dirname):
200 """Adds resource directories to Qt's search path"""
201 from PyQt4 import QtCore
202 resource_paths = resources.resource_dirs(dirname)
203 for r in resource_paths:
204 basename = os.path.basename(r)
205 QtCore.QDir.setSearchPaths(basename, [r])