Skip to content

Commit 3944a45

Browse files
committed
Merge branch 'develop'
Release kendall.0.4.2: * Performance improvements in status (updated to using gitpylib 0.4.2). * gl history is piped to less (updated to using gitpylib 0.4.2). * Output an error msg if the user provides a directory to file related ops. * Sort the files outputted by gl status so that it looks nicer. * Bug fixes.
2 parents a006aec + 5551eb7 commit 3944a45

15 files changed

+462
-103
lines changed

README.md

+20-39
Original file line numberDiff line numberDiff line change
@@ -1,46 +1,21 @@
11
Gitless
22
=======
33

4-
A version control system built on top of Git.
4+
Gitless is an experimental version control system built on top of Git. Many
5+
people complain that Git is hard to use. We think the problem lies deeper than
6+
the user interface, in the concepts underlying Git. Gitless is an experiment to
7+
see what happens if you put a simple veneer on an app that changes the
8+
underlying concepts. Because Gitless is implemented on top of Git (could be
9+
considered what Git pros call a 'porcelain' of Git), you can always fall
10+
back on Git. And of course your coworkers you share a repo with need never know
11+
that you're not a Git aficionado.
512

6-
This is under active development.
13+
More info, downloads and documentation @ [Gitless's website](
14+
http://people.csail.mit.edu/sperezde/gitless "Gitless's website").
715

8-
More info, downloads and documentation @
9-
<http://people.csail.mit.edu/sperezde/gitless>.
1016

11-
12-
About
13-
-----
14-
15-
Gitless is an experimental version control system built on top of Git. Keep in
16-
mind that Gitless might change in non-retrocompatible ways (so don't script
17-
around it just yet) as we seek to answer the fundamental question that drives
18-
this software project: if we were to challenge the very core concepts in
19-
version control systems, what would version control look like?
20-
21-
In its current state, Gitless is a distributed version control system that
22-
supports all of the most commonly used Git features. We are missing some things
23-
like submodules and cherry-picking but these are coming soon (maybe; only if we
24-
don't find a superior, more robust way of achieving the same goal). Either way,
25-
since Gitless is implemented on top of Git (could be considered what Git
26-
pros call a 'porcelain' of Git) you can always fallback to the 'git' command to
27-
finish a task.
28-
29-
Check out the documentation section to get started. If you are a novice user
30-
that never used any version control system the documentation should be enough to
31-
get you started. If you are a Git pro looking to see what's different from your
32-
beloved Git you'll be able to spot the differences by glancing through the
33-
documentation (section on Gitless vs. {Git, Mercurial} coming soon).
34-
35-
36-
Documentation
37-
-------------
38-
39-
TODO
40-
41-
42-
Installing
43-
----------
17+
Install
18+
-------
4419

4520
Note that the installation **won't interfere** with your Git installation in any
4621
way, you can keep using Git, and switch between Git and Gitless seamleslly.
@@ -58,11 +33,17 @@ You should now be able to start executing the `gl` command.
5833

5934

6035

61-
Contributing
62-
------------
36+
Contribute
37+
----------
6338

6439
We only have two branches, `master` and `develop`. We code in `develop` and
6540
merge the changes onto `master` when the changes are stable and we're ready to
6641
cut a new release. So you'll find on `develop` the latest changes.
6742

43+
We follow (to some extent) the [Google Python Style Guide](
44+
http://google-styleguide.googlecode.com/svn/trunk/pyguide.html
45+
"Google Python Style Guide").
46+
Before contributing, take a few seconds to look at the style guide and the
47+
Gitless's code so that your edits are consistent with the codebase.
48+
6849
To contribute: fork project, make changes, send pull request.

RELEASE_NOTES.md

+20-10
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,16 @@ Gitless's Release Notes
22
=======================
33

44

5+
15th Jan 2014 - kendall.0.4.2
6+
-----------------------------
7+
8+
* Performance improvements in status (updated to using gitpylib 0.4.2).
9+
* `gl history` is piped to less (updated to using gitpylib 0.4.2).
10+
* Output an error msg if the user provides a directory to file related ops.
11+
* Sort the files outputted by `gl status` so that it looks nicer.
12+
* Bug fixes.
13+
14+
515
6th Dec 2013 - kendall.0.4.1
616
----------------------------
717

@@ -11,7 +21,7 @@ Gitless's Release Notes
1121
23rd Nov 2013 - kendall.0.4
1222
---------------------------
1323

14-
* Revamped gl diff.
24+
* Revamped `gl diff`.
1525

1626

1727
28th Oct 2013 - kendall.0.3
@@ -20,8 +30,8 @@ Gitless's Release Notes
2030
* General bug fixes.
2131
* UI improvements (made some messages more clear, consistent).
2232
* Allow the user to branch out from certain commit point.
23-
* Improvements in gl diff: now it outputs a message if the file is ignored or if
24-
there are no diffs to show.
33+
* Improvements in `gl diff`: now it outputs a message if the file is ignored or
34+
if there are no diffs to show.
2535
* pre-commit hooks now work fine.
2636

2737

@@ -35,18 +45,18 @@ Gitless's Release Notes
3545
---------------------------
3646

3747
* Support for files with spaces.
38-
* General improvements in the gl checkout command:
39-
* Now the commit point is passed with the -cp flag (defaults to HEAD).
48+
* General improvements in the `gl checkout` command:
49+
* Now the commit point is passed with the `-cp` flag (defaults to `HEAD`).
4050
* Fixed bug that made it impossible to checkout a file without specifying
4151
its full repo path.
4252
* Ask for confirmation by the user if there are uncommitted changes that
4353
could be overwritten by checkout.
44-
* General improvements in the gl diff command:
54+
* General improvements in the `gl diff` command:
4555
* Fixed bug that made it impossible to diff a deleted file.
4656
* Now if no arguments are given all tracked files with modifications are
4757
diffed.
48-
* Removed the gl rm command.
49-
* Now gl is the only command (in retrospect, having a "suite of commands" was
58+
* Removed the `gl rm` command.
59+
* Now `gl` is the only command (in retrospect, having a "suite of commands" was
5060
over-engineering, code is much simpler now).
5161
* Massive re-org of project.
5262

@@ -57,8 +67,8 @@ Gitless's Release Notes
5767
* Minor improvements in output of commands.
5868
* Improvements in Makefile and added Python version checks.
5969
* Made case-sensitiveness consistent with FS.
60-
* Fixed bug that made it impossible to gl-track files under directories without
61-
cd'ing first to that dir.
70+
* Fixed bug that made it impossible to `gl-track` files under directories
71+
without cd'ing first to that dir.
6272
* Better support for evil branch names.
6373
* Before defaulting to using vim we now check to see if the user specified a
6474
value for Git's 'core.editor' config option or if the EDITOR env variable is

gitless/cli/file_cmd.py

+5
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
"""Helper module for gl_{track, untrack, resolve}."""
66

77

8+
import os
9+
810
import pprint
911

1012
from gitless.core import file as file_lib
@@ -32,6 +34,9 @@ def f(args):
3234
if ret == file_lib.FILE_NOT_FOUND:
3335
pprint.err('Can\'t {} a non-existent file: {}'.format(subcmd, fp))
3436
success = False
37+
elif ret == file_lib.FILE_IS_DIR:
38+
pprint.dir_err_exp(fp, subcmd)
39+
success = False
3540
elif ret is file_lib.FILE_ALREADY_UNTRACKED:
3641
pprint.err('File {} is already untracked'.format(fp))
3742
success = False

gitless/cli/gl.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77

88
import argparse
9+
import pkg_resources
910
import traceback
1011

1112
from gitless.core import repo as repo_lib
@@ -33,7 +34,7 @@
3334
INTERNAL_ERROR = 3
3435
NOT_IN_GL_REPO = 4
3536

36-
GL_VERSION = 'kendall.0.2.1'
37+
GL_VERSION = 'GL Version: ' + pkg_resources.require('gitless')[0].version
3738

3839

3940
def main():

gitless/cli/gl_checkout.py

+5-2
Original file line numberDiff line numberDiff line change
@@ -52,11 +52,14 @@ def _checkout_file(fp, cp):
5252
return False
5353

5454
ret, out = file_lib.checkout(fp, cp)
55-
if ret is file_lib.FILE_NOT_FOUND_AT_CP:
55+
if ret == file_lib.FILE_NOT_FOUND_AT_CP:
5656
pprint.err('Checkout aborted')
5757
pprint.err('There\'s no file %s at %s' % (fp, cp))
5858
return False
59-
elif ret is file_lib.SUCCESS:
59+
elif ret == file_lib.FILE_IS_DIR:
60+
pprint.dir_err_exp(fp, subcmd)
61+
return False
62+
elif ret == file_lib.SUCCESS:
6063
pprint.msg('File %s checked out sucessfully to its state at %s' % (fp, cp))
6164
return True
6265
else:

gitless/cli/gl_diff.py

+7-4
Original file line numberDiff line numberDiff line change
@@ -41,22 +41,25 @@ def main(args):
4141
for fp in files:
4242
ret, (out, padding) = file_lib.diff(fp)
4343

44-
if ret is file_lib.FILE_NOT_FOUND:
44+
if ret == file_lib.FILE_NOT_FOUND:
4545
pprint.err('Can\'t diff a non-existent file: {}'.format(fp))
4646
success = False
47-
elif ret is file_lib.FILE_IS_UNTRACKED:
47+
elif ret == file_lib.FILE_IS_UNTRACKED:
4848
pprint.err(
4949
'You tried to diff untracked file {}. It\'s probably a mistake. If '
5050
'you really care about changes in this file you should start '
5151
'tracking changes to it with gl track {}'.format(fp, fp))
5252
success = False
53-
elif ret is file_lib.FILE_IS_IGNORED:
53+
elif ret == file_lib.FILE_IS_IGNORED:
5454
pprint.err(
5555
'You tried to diff ignored file {}. It\'s probably a mistake. If '
5656
'you really care about changes in this file you should stop ignoring '
5757
'it by editing the .gigignore file'.format(fp))
5858
success = False
59-
elif ret is file_lib.SUCCESS:
59+
elif ret == file_lib.FILE_IS_DIR:
60+
pprint.dir_err_exp(fp, 'diff')
61+
success = False
62+
elif ret == file_lib.SUCCESS:
6063
if not out:
6164
pprint.msg(
6265
'The working version of file {} is the same as its last '

gitless/cli/gl_remote.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,8 @@ def _do_add(args):
4646
pprint.err_exp(
4747
'to get information about %s do gl remote show %s' % (rn, rn))
4848
pprint.err_exp(
49-
'if you want to change the url for remote %s do gl rm %s, and then gl '
50-
'add %s new_url' % (rn, rn, rn))
49+
'if you want to change the url for remote %s do gl remote rm %s, and '
50+
'then gl remote add %s new_url' % (rn, rn, rn))
5151
success = False
5252
elif ret is remote_lib.SUCCESS:
5353
pprint.msg('Remote added successfully')

gitless/cli/gl_status.py

+2
Original file line numberDiff line numberDiff line change
@@ -42,9 +42,11 @@ def main(unused_args):
4242
elif f.type == file_lib.UNTRACKED:
4343
untracked_list.append(f)
4444
pprint.blank()
45+
tracked_mod_list.sort(key=lambda f: f.fp)
4546
_print_tracked_mod_files(tracked_mod_list)
4647
pprint.blank()
4748
pprint.blank()
49+
untracked_list.sort(key=lambda f: f.fp)
4850
_print_untracked_files(untracked_list)
4951
return True
5052

gitless/cli/pprint.py

+5
Original file line numberDiff line numberDiff line change
@@ -67,3 +67,8 @@ def conf_dialog(msg):
6767
sys.stdout.write('# %s. Do you wish to continue? (y/N)' % msg)
6868
user_input = raw_input(' ')
6969
return user_input and user_input[0].lower() == 'y'
70+
71+
72+
def dir_err_exp(fp, subcmd):
73+
"""Prints the dir error exp to stderr."""
74+
err('{} is a directory. Can\'t {} a directory'.format(fp, subcmd))

gitless/core/file.py

+36-15
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,12 @@
2626
FILE_IS_IGNORED = 8
2727
FILE_NOT_IN_CONFLICT = 9
2828
FILE_ALREADY_RESOLVED = 10
29+
FILE_IS_DIR = 11
2930

3031
# Possible Gitless's file types.
31-
TRACKED = 11
32-
UNTRACKED = 12
33-
IGNORED = 13
32+
TRACKED = 12
33+
UNTRACKED = 13
34+
IGNORED = 14
3435

3536
# Possible diff output lines.
3637
DIFF_INFO = git_file.DIFF_INFO # line carrying diff info for new hunk.
@@ -46,9 +47,11 @@ def track(fp):
4647
fp: the file path of the file to track.
4748
4849
Returns:
49-
FILE_NOT_FOUND, FILE_ALREADY_TRACKED, FILE_IN_CONFLICT, FILE_IS_IGNORED or
50-
SUCCESS.
50+
FILE_NOT_FOUND, FILE_IS_DIR, FILE_ALREADY_TRACKED, FILE_IN_CONFLICT,
51+
FILE_IS_IGNORED or SUCCESS.
5152
"""
53+
if os.path.isdir(fp):
54+
return FILE_IS_DIR
5255
f_st, s = _status(fp)
5356
if f_st == FILE_NOT_FOUND:
5457
return FILE_NOT_FOUND
@@ -81,9 +84,11 @@ def untrack(fp):
8184
fp: the file path of the file to untrack.
8285
8386
Returns:
84-
FILE_NOT_FOUND, FILE_ALREADY_UNTRACKED, FILE_IN_CONFLICT, FILE_IS_IGNORED or
85-
SUCCESS.
87+
FILE_NOT_FOUND, FILE_IS_DIR, FILE_ALREADY_UNTRACKED, FILE_IN_CONFLICT,
88+
FILE_IS_IGNORED or SUCCESS.
8689
"""
90+
if os.path.isdir(fp):
91+
return FILE_IS_DIR
8792
f_st, s = _status(fp)
8893
if f_st == FILE_NOT_FOUND:
8994
return FILE_NOT_FOUND
@@ -122,11 +127,13 @@ def diff(fp):
122127
123128
Returns:
124129
a pair (result, out) where result is one of FILE_NOT_FOUND,
125-
FILE_IS_UNTRACKED or SUCCESS and out is the output of the diff command in a
126-
machine-friendly way: it's a tuple of the form
130+
FILE_IS_UNTRACKED, FILE_IS_DIR or SUCCESS and out is the output of the diff
131+
command in a machine-friendly way: it's a tuple of the form
127132
(list of namedtuples with fields 'line', 'status', 'old_line_number',
128133
'new_line_number', line number padding).
129134
"""
135+
if os.path.isdir(fp):
136+
return (FILE_IS_DIR, (None, None))
130137
f_st, s = _status(fp)
131138
if f_st == git_status.FILE_NOT_FOUND:
132139
return (FILE_NOT_FOUND, (None, None))
@@ -157,9 +164,11 @@ def checkout(fp, cp='HEAD'):
157164
cp: the commit point at which to checkout the file (defaults to HEAD).
158165
159166
Returns:
160-
a pair (status, out) where status is one of FILE_NOT_FOUND_AT_CP or SUCCESS
161-
and out is the content of fp at cp.
167+
a pair (status, out) where status is one of FILE_IS_DIR,
168+
FILE_NOT_FOUND_AT_CP or SUCCESS and out is the content of fp at cp.
162169
"""
170+
if os.path.isdir(fp):
171+
return (FILE_IS_DIR, None)
163172
# "show" expects the full path with respect to the repo root.
164173
rel_fp = os.path.join(repo_lib.cwd(), fp)[1:]
165174
ret, out = git_file.show(rel_fp, cp)
@@ -236,7 +245,9 @@ def resolve(fp):
236245
if f_st.resolved:
237246
return FILE_ALREADY_RESOLVED
238247

239-
# In Git, to mark a file as resolved we have to add it.
248+
# We don't use Git to keep track of resolved files, but just to make it feel
249+
# like doing a resolve in Gitless is similar to doing a resolve in Git
250+
# (i.e., add) we stage the file.
240251
git_file.stage(fp)
241252
# We add a file in the Gitless directory to be able to tell when a file has
242253
# been marked as resolved.
@@ -278,7 +289,17 @@ def _build_f_st(s, fp):
278289
elif s == git_status.TRACKED_MODIFIED:
279290
ret = FileStatus(fp, TRACKED, True, True, True, False, False)
280291
elif s == git_status.STAGED:
281-
# Staged file don't exist in the lr for Gitless.
292+
# A file could have been "gl track"ed and later ignored by adding a matching
293+
# pattern in a .gitignore file. We consider this kind of file to still be a
294+
# tracked file. This is consistent with the idea that tracked files can't
295+
# be ignored.
296+
# TODO(sperezde): address the following rough edge: the user could untrack
297+
# a tracked file (one that was not committed before) and if it's matched by
298+
# a .gitignore file it will be ignored. The same thing won't happen if an
299+
# already committed file is untracked (due to how Gitless keeps track of
300+
# these kind of files).
301+
302+
# Staged files don't exist in the lr for Gitless.
282303
ret = FileStatus(fp, TRACKED, False, True, True, False, False)
283304
elif s == git_status.ASSUME_UNCHANGED:
284305
# TODO(sperezde): detect whether it is modified or not?
@@ -287,15 +308,15 @@ def _build_f_st(s, fp):
287308
ret = FileStatus(fp, TRACKED, True, False, True, False, False)
288309
elif s == git_status.DELETED_STAGED:
289310
# This can only happen if the user did a rm of a new file. The file doesn't
290-
# exist anymore for Gitless.
311+
# exist as far as Gitless is concerned.
291312
git_file.unstage(fp)
292313
ret = None
293314
elif s == git_status.DELETED_ASSUME_UNCHANGED:
294315
ret = None
295316
elif s == git_status.IN_CONFLICT:
296317
wr = _was_resolved(fp)
297318
ret = FileStatus(fp, TRACKED, True, True, True, not wr, wr)
298-
elif s == git_status.IGNORED or s == git_status.IGNORED_STAGED:
319+
elif s == git_status.IGNORED:
299320
ret = FileStatus(fp, IGNORED, False, True, True, True, False)
300321
elif s == git_status.MODIFIED_MODIFIED:
301322
# The file was marked as resolved and then modified. To Gitless, this is

0 commit comments

Comments
 (0)