Git development
 help / color / mirror / Atom feed
* Re: [PATCH 1/2] gitweb: New improved patchset view
From: Junio C Hamano @ 2006-11-08 18:27 UTC (permalink / raw)
  To: Jakub Narebski; +Cc: git
In-Reply-To: <200611081759.41498.jnareb@gmail.com>

Jakub Narebski <jnareb@gmail.com> writes:

> ---
>  gitweb/gitweb.css  |   66 +++++++++++++++----
>  gitweb/gitweb.perl |  183 
> ++++++++++++++++++++++++++++++++++------------------
>  2 files changed, 173 insertions(+), 76 deletions(-)

Linewrap?

> ----------------------------------------------------------------------
>  ## functions returning short HTML fragments, or transforming HTML 
> fragments

...

^ permalink raw reply

* Re: [PATCH 2/2] gitweb: Use character or octal escape codes (and add span.cntrl) in esc_path
From: Junio C Hamano @ 2006-11-08 18:24 UTC (permalink / raw)
  To: Jakub Narebski; +Cc: git
In-Reply-To: <200611081150.07469.jnareb@gmail.com>

Jakub Narebski <jnareb@gmail.com> writes:

> Instead of simply hiding control characters in esc_path by replacing
> them with '?', use Character Escape Codes (CEC) i.e. alphabetic
> backslash sequences like those found in C programming language and
> many other languages influenced by it, such as Java and Perl.  If
> control characted doesn't have corresponding character escape code,
> use octal char sequence to escape it.
>
> Additionally use 'span' element with 'cntrl' attribute to mark escaped
> control characters. Add style for span.cntrl in the CSS.

Would have preferred the 'span' thing to be part of [1/2]...

Didn't I ask quot to be freestanding sub, not nested?  That
would make UPR vs CEC experiments easier and more pleasant.

^ permalink raw reply

* Re: Shallow clone [Was Re: What's in git.git ]
From: Aneesh Kumar K.V @ 2006-11-08 17:59 UTC (permalink / raw)
  To: Aneesh Kumar K.V; +Cc: git
In-Reply-To: <45520872.3090506@gmail.com>

[-- Attachment #1: Type: text/plain, Size: 1291 bytes --]

Aneesh Kumar K.V wrote:
> David Lang wrote:
>> On Tue, 7 Nov 2006, Junio C Hamano wrote:
>>
>>> [pu]
>>>
>>>  Johannes's shallow clone work now should rebase cleanly on top
>>>  of 'master' although I haven't done so yet.  As he said
>>>  himself the series is waiting for people who have needs for
>>>  such a feature to raise hands.
>>
>> I haven't been watching this recently, but if this is what I 
>> understand it to be (the ability to get a partial repository from 
>> upstream and work normally from there with the result of data-mineing 
>> tools sometimes reporting 'that's part of the truncated history' if 
>> they hit the cutoff) consider my hand raised.
>>
>> there are a number of cases where I would be interested in following a 
>> project as it moves forwards, but do not have the need to have the 
>> full history (even with the good compression that a git pack provides, 
>> it's still a significant amount of disk space and download time for 
>> large projects)
>>
> 
> I am trying to test this feature. Is there a documentation .git/shallow 
> some where. Atleast what those entries
> mean ? I know in the mail johannes mentioned only core git will touch 
> this file. But it should be ok to be descriptive like other files. 
> (FETCH_HEAD)


How about this 

-aneesh 

[-- Attachment #2: repository-layout.txt.diff --]
[-- Type: text/x-patch, Size: 537 bytes --]

diff --git a/Documentation/repository-layout.txt b/Documentation/repository-layout.txt
index 275d18b..03a6f77 100644
--- a/Documentation/repository-layout.txt
+++ b/Documentation/repository-layout.txt
@@ -141,3 +141,9 @@ logs/refs/heads/`name`::
 
 logs/refs/tags/`name`::
 	Records all changes made to the tag named `name`.
+
+shallow::
+	Records the sha1 of the commits which is marked to have no
+	parents to represent a shallow repository.The commit object
+	will have the parent information present. It carry one
+	record per line.

^ permalink raw reply related

* Re: Did anyone have trouble learning the idea of local vs. remote branches?
From: Jakub Narebski @ 2006-11-08 17:36 UTC (permalink / raw)
  To: Wink Saville; +Cc: git
In-Reply-To: <4552088D.6040709@saville.com>

Please leave only the parts you are replying to when replying.
Thanks in advance.

Wink Saville wrote:
> Jakub Narebski wrote:
>> Wink Saville wrote:
>> 
>>> It turns out the instructions were incorrect and Junio was 
>>> kind enough to correct the mistake. But I for one am still confused.  
>>>
>>>   git-fetch is; "Download objects and a head from another repository"
>>>
>>> Fair enough and that make sense, but where does it go? Apparently it just
>>> gets stored in the object database and a reference to it in "FETCH_HEAD".
>>> Now what? Ok the documentation says:  
>> 
>> Objects gets stored into object database. Then (using FETCH_HEAD) heads
>> of tracking branches gets updated (i.e. if there were some changes on
>> branch 'master' in remote, the objects are downloaded, then head of local
>> tracking branch corresponding to remote branch 'master', e.g. 'origin',
>> gets updated with the value in 'master'; so called fast-forward case).
>>  
> 
> OK, so fetch does more than just fetching, it also merges, confusing 
> especially given the that the Description says otherwise.

No, git-fetch just (for each head/each branch) download the changes,
_and_ updates head i.e. pointer to the downloaded changes. Without updating
head you wouldn't be able to access downloaded changes. git-fetch doesn't
do merge: it does only fast-forward.

For example, if you have on your branch 'next':

  [local]   A---B---C <-- next

and the repository you fetch from has few more commits:

  [remote]  A---B---C---D---E <-- next

git-fetch downloads the objects (see that graoh for [local] is subgraph
of graph for [remote] - this is fast-forward case)

  [local]   A---B---C---D---E
                    ^
                    \--- next

and then updates next, but only in fast-forward case (the exception being
that you can demand fetch also for non-fast forward case)

  [local]  A---B---C---D---E <-- next

> I just searched git-fetch documentation and I see it mentioned under the 
> <refspec> documentation. I read the words but why do I have to tell it 
> what the source & destination. From my perspective the source is the url 
> and the destination is my repository. So refspec doesn't make sense, of 
> course it's my problem I'm not blaming git or the documentation. But as 
> a newbie I'm confused.

The confusion seems to descend from the fact, that there can be multiple
branches in git repository. When fetching, you must provide the URL to the
repository, which remote branches do you want to download, and what those
tracking branches should be named in your repository. You can create shortcut
name which contains all those info: the URL of repository and the <refspecs>,
i.e. mapping from remote branches (which you want to download) names to the
local branch names (what you want to save them as...) either as so called
'remotes' file (file in .git/remotes) or, in latest version of git, in the
repository config. git-clone (or git-clone --use-separate-remotes)
creates remote file called 'origin', so you can use "git fetch origin" to
fetch the changes made since the time you cloned the repository or fetched
from it.
 
> As I continue to investigate the <refspec> documentation it mentions in 
> the first "Note" that ".. rewound and rebased frequently, the a pull .." 
> . OK, so why is "pull" mentioned here I'm not pulling I'm fetching. Of 
> course if you go to the git-pull documentation we see the <refspec> 
> repeated. Which maybe isn't surprising since pull is a fetch+merge. So I 
> guess the confusing part is that fetch does do merging, even though it 
> says it implies it doesn't.

Again: fetch does not do merging. It's historical that the fetch refspecs
are called "Pull:" lines.

>>> Now in the case of fetching -mm apparently you don't do a merge, instead
>>> the instructions now read: 
>>>
>>>   $ git-fetch \
>>>     git://git.kernel.org/pub/scm/linux/kernel/git/smurf/linux-trees.git \
>>>     tag v2.6.16-rc2-mm1  
>>>   $ git-checkout -b local-v2.6.16-rc2-mm1 v2.6.16-rc2-mm1
>> 
>> Are you sure that it is 'tag' there?
> 
> Yes, this is directly from Junio.

Ooops, I haven't read git-fetch(1) carefully enough:

  Some short-cut notations are also supported.

  * tag <tag> means the same as refs/tags/<tag>:refs/tags/<tag>;  it
    requests fetching everything up to the given tag.

>>> Secondly, what is the relationship between "remote branch heads" and
>>> FETCH_HEAD? I see no mention of FETCH_HEAD or how it might be used
>>> anywhere in the git-merge documentation.
>> 
>> FETCH_HEAD is low-lewel, not to be used by end-user (unless he/she wants to
>> do something unusual).
> 
> Then why mention it at all?

Obsolete documentation? It's agreed that git-merge is neither fish nor fowl,
neither plumbing (engine) command, nor truly porcelain (UI) command.

You should rather use git-pull, than run git-merge by hand. git-pull uses
git-merge, with FETCH_HEAD as one of arguments.
 
>>> Then we come to "the index file 
>>> must exactly match the tree HEAD commit", sorry but my question is how
>>> could it not match? 
>> 
>> For example if you git-add'ed some files, but not committed the addition.

Or git-update-index some file, or you are in the middle of resolving
merge conflict, or you removed some files...
 
> But if I've added some files, it would seem perfectly reasonable that 
> git could still "merge" unless the new files conflicted with new files 
> in the fetch.

In which case it would be too late. Git detects possibility of conflict
(not clean index), and aborts early.

>>> It then goes onto say "it may fetch the objects from remote" I thought
>>> that is what "fetch" does. 
>> 
>> IIRC this explanation is in git-pull(1). Pull in git is _fetch_ + merge.
>>  
> 
> So a source of confusion is fetch also does merging/fast-forwarding, 
> this is confusing. Fetch should fetch, merge should merge, pull should 
> do both.

Fetch without updating refs would mean no access to downloaded objects.
Refs updating happend only (unless forced) in fast-forward case, i.e.
in the case of merge which is not a merge.

> Another source of confusion is we start out with two branches after 
> cloning _master_ & _origin_. Now if I create my own branch and check it 
> out and then do a pull, what is going to be merged where and when?

Use --use-separate-remotes if master/origin confuses you. In short:
 
without --use-separate-remotes:

   local branch    | remote branch   | can commit  | should commit
   ----------------------------------------------------------------
   master          | ----            | Yes         | Yes
   origin          | master          | Yes         | No
   next            | next            | Yes         | No

Master branch is for _your_ work. When you are on master branch, and do
'git pull', git does fetching and the merges _topmost_ branch in remotes
file ('origin') into current branch ('master').

with --use-separate-remotes

   local branch          | remote branch | can commit | should commit
   ------------------------------------------------------------------
   master                | ----          | Yes        | Yes
   remotes/origin/master | master        | No         | No
   remotes/origin/next   | next          | No         | No

> I need to read, re-read and actually understand git-merge the "Grand 
> Unified Merge Driver", I can see it's very powerful but with that power 
> comes confusion.

Don't use git-merge. Use git-pull. If you want merge local branches, use
'.' as the name of repository (means here: local repository).
 
Yes, this is confusing. Historical reasons, most probably.

[...]
-- 
Jakub Narebski

^ permalink raw reply

* Re: win2k/cygwin cannot handle even moderately sized packs
From: Shawn Pearce @ 2006-11-08 17:11 UTC (permalink / raw)
  To: Alex Riesen; +Cc: Jakub Narebski, Junio C Hamano, git
In-Reply-To: <81b0412b0611080537k1087be66x1a4a9686b43d7b46@mail.gmail.com>

Alex Riesen <raa.lkml@gmail.com> wrote:
> >The use counter.  Every time someone asks for a pointer into the
> >pack they need to lock that window into memory to prevent us from
> >garbage collecting it by unmapping it to make room for another
> >window that the application needs.
> 
> I think the counters can be kept in struct packed_git somewhere. Given mmap
> granularity, and the fact that not all of the pack is used in normal case
> (and the granularity help us in the worst case) the memory used up by the
> page counters shouldn't be too much.

We already have a counter in struct packed_git (pack_use_cnt),
but this counter and struct permits only one mmap per pack.
We actually want at least two, but really four sliding windows
per pack.  Here's why:

The commits are at the front of the pack, trees are somewhere just
behind them, and the blobs are behind that.  The objects are also
loosely ordered by time, so the further back in the commit graph
you go the associated data is closer to the end of the pack file.

If a pack file is larger than our mmap unit (32 MiB in my
implementation) then we will mmap it in at least two different
non-contiguous windows.  In the case of the Linux kernel pack
(>128 MiB now) that's at least 4 windows to mmap the entire file.

If we are a commit parsing application (merge-base, blame, log,
rev-list, etc...) we need to walk back along the commit DAG to
identify objects of interest.  So we need the front of the pack
mmap'd.  But if we have a path filter than we also need to mmap the
middle of the pack to get access to the trees; and if we need blob
data than we need to mmap near the back too to get those.

So really an application wants 2-3 sliding windows of a pack file;
one focused on the front covering the unparsed commits; one slightly
behind that focused on the trees; and one further back focused on
the blobs.  Oh and you may actually need a 4th to do delta base
decompression.  If you work with less than 4 sliding windows then
you are going to be thrashing the page tables somewhat as you toss
out one window to load another, then toss that window out just to
go back and reaccess the one you previously tossed.

If the sliding window size is large enough that nearly all commits
and trees fit into it then this is mostly a non-issue.  Heck the
git.git pack is hovering around 10 MiB these days; that's less than
one window.  But when the pack is larger than a couple of windows
this really starts to matter...  and that's specifically the type
of repository this feature is designed for.

> >All true.  However what happens when the header spans two windows?
> >Lets say I have the first 4 MiB mapped and the next 4 MiB mapped in
> >a different window; these are not necessarily at the same locations
> >within memory.  Now if an object header is split over these two
> >then some bytes are at the end of the first window and the rest
> >are at the start of the next window.
> 
> Assuming these are adjacent windows, we can just increment counters on the
> all touched pages (at least the two together) and return the pointer into
> the lowest page. Otherwise - time for garbage collection (why produce the
> garbage at all, btw?) and remap.

They are adjacent in the pack file but not necessarily in virtual memory!

I'm just asking the OS to return me a mapping for a chunk of a file;
I'm not also trying to make them contiguous in virtual memory.

Making adjacent pack file chunks contiguous in virtual memory is even
more code and probably going to cause problems at runtime.  How do
we know what area of virtual memory is mostly unused on any given
platform?  Any application that I have seen that tries to manage
its own virtual memory layout is usually full of platform specific
hacks to make it work everywhere. Lets not go there with Git.

The garbage creation is to account for the 2-4 windows required
by most applications.  Most of the time each window is unused;
we really only have two windows in use during delta decompression,
at all other times we really only have 1 window in use.  The commit
parsing applications don't keep the commit window in use when they
go access a tree or a blob.

Consequently we want the garbage there.  Actually I shouldn't have
used garbage: the correct term would be LRU managed cache.  :-)
When we need a new window and we would exceed our maximum limit
(128 MiB in my implementation) we unmap the least recently used
window which is not currently in use.

> >I can't just say "make sure we have at least X bytes available
> >before starting to decode the header, as to do that in this case
> >we'd have to unmap BOTH windows and remap a new one which keeps
> >that very small header fully contiguous in memory.  That's thrashing
> >the VM page tables for really no benefit.
> 
> You can't mmap less than a page, can you? So it's actually never a small
> portion, but at least 4k on x86.

No.  But we always mmap even more than that per window; e.g. 32
MiB.  Since the header is way smaller than 4k we're talking about
unmapping two 32 MiB windows and remapping one of them just one
page earlier to get the whole object header in a contiguous region.
I'm not a kernel hacker (nor do I pretended to be) but from what I
know of the x86 page table structure that's not exactly the fastest
operation we can ask the system to perform.  :)

I could be wrong.  It may not matter.  But I think its crazy to
unmap otherwise valid mappings just because 2 bytes are on the
wrong side of an arbitrary boundary.

-- 

^ permalink raw reply

* [PATCH 2/2] gitweb: New improved formatting of chunk header in diff
From: Jakub Narebski @ 2006-11-08 17:00 UTC (permalink / raw)
  To: git
In-Reply-To: <200611081758.57597.jnareb@gmail.com>

If we have provided enough info, and diff is not combined diff,
and if provided diff line is chunk header, then:
* split chunk header into .chunk_info and .section span elements,
  first containing proper chunk header, second section heading
  (aka. which function), for separate styling: the proper chunk
  header is on non-white background, section heading part uses
  slightly lighter color.
* hyperlink from-file-range to starting line of from-file, if file
  was not created.
* hyperlink to-file-range to starting line of to-file, if file
  was not deleted.
Links are of invisible variety (and "list" class).

Signed-off-by: Jakub Narebski <jnareb@gmail.com>
---
 gitweb/gitweb.css  |   13 +++++++++++++
 gitweb/gitweb.perl |   18 +++++++++++++++++-
 2 files changed, 30 insertions(+), 1 deletions(-)

diff --git a/gitweb/gitweb.css b/gitweb/gitweb.css
index 974b47f..7177c6e 100644
--- a/gitweb/gitweb.css
+++ b/gitweb/gitweb.css
@@ -334,11 +334,13 @@ div.diff.extended_header {
 	padding: 2px 0px 2px 0px;
 }
 
+div.diff a.list,
 div.diff a.path,
 div.diff a.hash {
 	text-decoration: none;
 }
 
+div.diff a.list:hover,
 div.diff a.path:hover,
 div.diff a.hash:hover {
 	text-decoration: underline;
@@ -362,14 +364,25 @@ div.diff.rem {
 	color: #cc0000;
 }
 
+div.diff.chunk_header a,
 div.diff.chunk_header {
 	color: #990099;
+}
 
+div.diff.chunk_header {
 	border: dotted #ffe0ff;
 	border-width: 1px 0px 0px 0px;
 	margin-top: 2px;
 }
 
+div.diff.chunk_header span.chunk_info {
+	background-color: #ffeeff;
+}
+
+div.diff.chunk_header span.section {
+	color: #aa22aa;
+}
+
 div.diff.incomplete {
 	color: #cccccc;
 }
diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl
index 2cf8e60..3118cb0 100755
--- a/gitweb/gitweb.perl
+++ b/gitweb/gitweb.perl
@@ -873,6 +873,7 @@ sub format_subject_html {
 
 sub format_diff_line {
 	my $line = shift;
+	my ($from, $to) = @_;
 	my $char = substr($line, 0, 1);
 	my $diff_class = "";
 
@@ -888,6 +889,21 @@ sub format_diff_line {
 		$diff_class = " incomplete";
 	}
 	$line = untabify($line);
+	if ($from && $to && $line =~ m/^\@{2} /) {
+		my ($from_text, $from_start, $from_lines, $to_text, $to_start, $to_lines, $section) =
+			$line =~ m/^\@{2} (-(\d+),(\d+)) (\+(\d+),(\d+)) \@{2}(.*)$/;
+		if ($from->{'href'}) {
+			$from_text = $cgi->a({-href=>"$from->{'href'}#l$from_start",
+			                     -class=>"list"}, $from_text);
+		}
+		if ($to->{'href'}) {
+			$to_text   = $cgi->a({-href=>"$to->{'href'}#l$to_start",
+			                     -class=>"list"}, $to_text);
+		}
+		$line = "<span class=\"chunk_info\">@@ $from_text $to_text @@</span>" .
+		        "<span class=\"section\">" . esc_html($section, -nbsp=>1) . "</span>";
+		return "<div class=\"diff$diff_class\">$line</div>\n";
+	}
 	return "<div class=\"diff$diff_class\">" . esc_html($line, -nbsp=>1) . "</div>\n";
 }
 
@@ -2323,7 +2339,7 @@ sub git_patchset_body {
 			next LINE;
 		}
 
-		print format_diff_line($patch_line);
+		print format_diff_line($patch_line, \%from, \%to);
 	}
 	print "</div>\n" if $patch_found; # class="patch"
 
-- 
1.4.3.4

^ permalink raw reply related

* [PATCH 1/2] gitweb: New improved patchset view
From: Jakub Narebski @ 2006-11-08 16:59 UTC (permalink / raw)
  To: git
In-Reply-To: <200611081758.57597.jnareb@gmail.com>

Replace "gitweb diff header" with its full sha1 of blobs and replace
it by "git diff" header and extended diff header. Change also somewhat
highlighting of diffs.

Added `file_type_long' subroutine to convert file mode in octal to
file type description (only for file modes which used by git).

Changes:
* "gitweb diff header" which looked for example like below:
    file:_<sha1 before>_ -> file:_<sha1 after>_
  where 'file' is file type and '<sha1>' is full sha1 of blob is
  changed to
    diff --git _a/<file before>_ _b/<file after>_
  In both cases links are visible and use default link style. If file
  is added, a/<file> is not hyperlinked. If file is deleted, b/<file>
  is not hyperlinked.
* there is added "extended diff header", with <path> and <hash>
  hyperlinked (and <hash> shortened to 7 characters), and <mode>
  explained: '<mode>' is extended to '<mode> (<file type description>)',
  where added text is slightly lighter to easy distinguish that it
  was added (and it is difference from git-diff output).
* from-file/to-file two-line header lines have slightly darker color
  than removed/added lines.
* chunk header has now delicate line above for easier finding chunk
  boundary, and top margin of 2px, both barely visible.

Signed-off-by: Jakub Narebski <jnareb@gmail.com>
---
 gitweb/gitweb.css  |   66 +++++++++++++++----
 gitweb/gitweb.perl |  183 
++++++++++++++++++++++++++++++++++------------------
 2 files changed, 173 insertions(+), 76 deletions(-)

diff --git a/gitweb/gitweb.css b/gitweb/gitweb.css
index e19e6bc..974b47f 100644
--- a/gitweb/gitweb.css
+++ b/gitweb/gitweb.css
@@ -298,40 +298,82 @@ td.mode {
 	font-family: monospace;
 }
 
-div.diff a.list {
+/* styling of diffs (patchsets): commitdiff and blobdiff views */
+div.diff.header,
+div.diff.extended_header {
+	white-space: normal;
+}
+
+div.diff.header {
+	font-weight: bold;
+
+	background-color: #edece6;
+
+	margin-top: 4px;
+	padding: 4px 0px 2px 0px;
+	border: solid #d9d8d1;
+	border-width: 1px 0px 1px 0px;
+}
+
+div.diff.header a.path {
+	text-decoration: underline;
+}
+
+div.diff.extended_header,
+div.diff.extended_header a.path,
+div.diff.extended_header a.hash {
+	color: #777777;
+}
+
+div.diff.extended_header .info {
+	color: #b0b0b0;
+}
+
+div.diff.extended_header {
+	background-color: #f6f5ee;
+	padding: 2px 0px 2px 0px;
+}
+
+div.diff a.path,
+div.diff a.hash {
 	text-decoration: none;
 }
 
-div.diff a.list:hover {
+div.diff a.path:hover,
+div.diff a.hash:hover {
 	text-decoration: underline;
 }
 
-div.diff.to_file a.list,
-div.diff.to_file,
+div.diff.to_file a.path,
+div.diff.to_file {
+	color: #007000;
+}
+
 div.diff.add {
 	color: #008800;
 }
 
-div.diff.from_file a.list,
-div.diff.from_file,
+div.diff.from_file a.path,
+div.diff.from_file {
+	color: #aa0000;
+}
+
 div.diff.rem {
 	color: #cc0000;
 }
 
 div.diff.chunk_header {
 	color: #990099;
+
+	border: dotted #ffe0ff;
+	border-width: 1px 0px 0px 0px;
+	margin-top: 2px;
 }
 
 div.diff.incomplete {
 	color: #cccccc;
 }
 
-div.diff_info {
-	font-family: monospace;
-	color: #000099;
-	background-color: #edece6;
-	font-style: italic;
-}
 
 div.index_include {
 	border: solid #d9d8d1;
diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl
index c9b16b5..2cf8e60 100755
--- a/gitweb/gitweb.perl
+++ b/gitweb/gitweb.perl
@@ -780,6 +780,32 @@ sub file_type {
 	}
 }
 
+# convert file mode in octal to file type description string
+sub file_type_long {
+	my $mode = shift;
+
+	if ($mode !~ m/^[0-7]+$/) {
+		return $mode;
+	} else {
+		$mode = oct $mode;
+	}
+
+	if (S_ISDIR($mode & S_IFMT)) {
+		return "directory";
+	} elsif (S_ISLNK($mode)) {
+		return "symlink";
+	} elsif (S_ISREG($mode)) {
+		if ($mode & S_IXUSR) {
+			return "executable";
+		} else {
+			return "file";
+		};
+	} else {
+		return "unknown";
+	}
+}
+
+
 ## 
----------------------------------------------------------------------
 ## functions returning short HTML fragments, or transforming HTML 
fragments
 ## which don't beling to other sections
@@ -2166,6 +2192,7 @@ sub git_patchset_body {
 	my $in_header = 0;
 	my $patch_found = 0;
 	my $diffinfo;
+	my (%from, %to);
 
 	print "<div class=\"patchset\">\n";
 
@@ -2176,6 +2203,10 @@ sub git_patchset_body {
 		if ($patch_line =~ m/^diff /) { # "git diff" header
 			# beginning of patch (in patchset)
 			if ($patch_found) {
+				# close extended header for previous empty patch
+				if ($in_header) {
+					print "</div>\n" # class="diff extended_header"
+				}
 				# close previous patch
 				print "</div>\n"; # class="patch"
 			} else {
@@ -2184,89 +2215,113 @@ sub git_patchset_body {
 			}
 			print "<div class=\"patch\" id=\"patch". ($patch_idx+1) ."\">\n";
 
+			# read and prepare patch information
 			if (ref($difftree->[$patch_idx]) eq "HASH") {
+				# pre-parsed (or generated by hand)
 				$diffinfo = $difftree->[$patch_idx];
 			} else {
 				$diffinfo = parse_difftree_raw_line($difftree->[$patch_idx]);
 			}
+			$from{'file'} = $diffinfo->{'from_file'} || $diffinfo->{'file'};
+			$to{'file'}   = $diffinfo->{'to_file'}   || $diffinfo->{'file'};
+			if ($diffinfo->{'status'} ne "A") { # not new (added) file
+				$from{'href'} = href(action=>"blob", hash_base=>$hash_parent,
+				                     hash=>$diffinfo->{'from_id'},
+				                     file_name=>$from{'file'});
+			}
+			if ($diffinfo->{'status'} ne "D") { # not deleted file
+				$to{'href'} = href(action=>"blob", hash_base=>$hash,
+				                   hash=>$diffinfo->{'to_id'},
+				                   file_name=>$to{'file'});
+			}
 			$patch_idx++;
 
-			if ($diffinfo->{'status'} eq "A") { # added
-				print "<div class=\"diff_info\">" . 
file_type($diffinfo->{'to_mode'}) . ":" .
-				      $cgi->a({-href => href(action=>"blob", hash_base=>$hash,
-				                             hash=>$diffinfo->{'to_id'}, 
file_name=>$diffinfo->{'file'})},
-				              $diffinfo->{'to_id'}) . " (new)" .
-				      "</div>\n"; # class="diff_info"
-
-			} elsif ($diffinfo->{'status'} eq "D") { # deleted
-				print "<div class=\"diff_info\">" . 
file_type($diffinfo->{'from_mode'}) . ":" .
-				      $cgi->a({-href => href(action=>"blob", 
hash_base=>$hash_parent,
-				                             hash=>$diffinfo->{'from_id'}, 
file_name=>$diffinfo->{'file'})},
-				              $diffinfo->{'from_id'}) . " (deleted)" .
-				      "</div>\n"; # class="diff_info"
-
-			} elsif ($diffinfo->{'status'} eq "R" || # renamed
-			         $diffinfo->{'status'} eq "C" || # copied
-			         $diffinfo->{'status'} eq "2") { # with two filenames (from 
git_blobdiff)
-				print "<div class=\"diff_info\">" .
-				      file_type($diffinfo->{'from_mode'}) . ":" .
-				      $cgi->a({-href => href(action=>"blob", 
hash_base=>$hash_parent,
-				                             hash=>$diffinfo->{'from_id'}, 
file_name=>$diffinfo->{'from_file'})},
-				              $diffinfo->{'from_id'}) .
-				      " -> " .
-				      file_type($diffinfo->{'to_mode'}) . ":" .
-				      $cgi->a({-href => href(action=>"blob", hash_base=>$hash,
-				                             hash=>$diffinfo->{'to_id'}, 
file_name=>$diffinfo->{'to_file'})},
-				              $diffinfo->{'to_id'});
-				print "</div>\n"; # class="diff_info"
-
-			} else { # modified, mode changed, ...
-				print "<div class=\"diff_info\">" .
-				      file_type($diffinfo->{'from_mode'}) . ":" .
-				      $cgi->a({-href => href(action=>"blob", 
hash_base=>$hash_parent,
-				                             hash=>$diffinfo->{'from_id'}, 
file_name=>$diffinfo->{'file'})},
-				              $diffinfo->{'from_id'}) .
-				      " -> " .
-				      file_type($diffinfo->{'to_mode'}) . ":" .
-				      $cgi->a({-href => href(action=>"blob", hash_base=>$hash,
-				                             hash=>$diffinfo->{'to_id'}, 
file_name=>$diffinfo->{'file'})},
-				              $diffinfo->{'to_id'});
-				print "</div>\n"; # class="diff_info"
+			# print "git diff" header
+			$patch_line =~ s!^(diff (.*?) )"?a/.*$!$1!;
+			if ($from{'href'}) {
+				$patch_line .= $cgi->a({-href => $from{'href'}, -class => "path"},
+				                       'a/' . esc_path($from{'file'}));
+			} else { # file was added
+				$patch_line .= 'a/' . esc_path($from{'file'});
+			}
+			$patch_line .= ' ';
+			if ($to{'href'}) {
+				$patch_line .= $cgi->a({-href => $to{'href'}, -class => "path"},
+				                       'b/' . esc_path($to{'file'}));
+			} else { # file was deleted
+				$patch_line .= 'b/' . esc_path($to{'file'});
 			}
 
-			#print "<div class=\"diff extended_header\">\n";
+			print "<div class=\"diff header\">$patch_line</div>\n";
+			print "<div class=\"diff extended_header\">\n";
 			$in_header = 1;
 			next LINE;
-		} # start of patch in patchset
+		}
 
+		if ($in_header) {
+			if ($patch_line !~ m/^---/) {
+				# match <path>
+				if ($patch_line =~ s!^((copy|rename) from ).*$!$1! && 
$from{'href'}) {
+					$patch_line .= $cgi->a({-href=>$from{'href'}, -class=>"path"},
+					                        esc_path($from{'file'}));
+				}
+				if ($patch_line =~ s!^((copy|rename) to ).*$!$1! && $to{'href'}) {
+					$patch_line = $cgi->a({-href=>$to{'href'}, -class=>"path"},
+					                      esc_path($to{'file'}));
+				}
+				# match <mode>
+				if ($patch_line =~ m/\s(\d{6})$/) {
+					$patch_line .= '<span class="info"> (' .
+					               file_type_long($1) .
+					               ')</span>';
+				}
+				# match <hash>
+				if ($patch_line =~ m/^index/) {
+					my ($from_link, $to_link);
+					if ($from{'href'}) {
+						$from_link = $cgi->a({-href=>$from{'href'}, -class=>"hash"},
+						                     substr($diffinfo->{'from_id'},0,7));
+					} else {
+						$from_link = '0' x 7;
+					}
+					if ($to{'href'}) {
+						$to_link = $cgi->a({-href=>$to{'href'}, -class=>"hash"},
+						                   substr($diffinfo->{'to_id'},0,7));
+					} else {
+						$to_link = '0' x 7;
+					}
+					my ($from_id, $to_id) = ($diffinfo->{'from_id'}, 
$diffinfo->{'to_id'});
+					$patch_line =~ s!$from_id\.\.$to_id!$from_link..$to_link!;
+				}
+				print $patch_line . "<br/>\n";
 
-		if ($in_header && $patch_line =~ m/^---/) {
-			#print "</div>\n"; # class="diff extended_header"
-			$in_header = 0;
+			} else {
+				#$in_header && $patch_line =~ m/^---/;
+				print "</div>\n"; # class="diff extended_header"
+				$in_header = 0;
+
+				if ($from{'href'}) {
+					$patch_line = '--- a/' .
+					              $cgi->a({-href=>$from{'href'}, -class=>"path"},
+					                      esc_path($from{'file'}));
+				}
+				print "<div class=\"diff from_file\">$patch_line</div>\n";
 
-			my $file = $diffinfo->{'from_file'};
-			$file  ||= $diffinfo->{'file'};
-			$file = $cgi->a({-href => href(action=>"blob", 
hash_base=>$hash_parent,
-			                               hash=>$diffinfo->{'from_id'}, 
file_name=>$file),
-			                -class => "list"}, esc_path($file));
-			$patch_line =~ s|a/.*$|a/$file|g;
-			print "<div class=\"diff from_file\">$patch_line</div>\n";
+				$patch_line = <$fd>;
+				chomp $patch_line;
 
-			$patch_line = <$fd>;
-			chomp $patch_line;
+				#$patch_line =~ m/^+++/;
+				if ($to{'href'}) {
+					$patch_line = '+++ b/' .
+					              $cgi->a({-href=>$to{'href'}, -class=>"path"},
+					                      esc_path($to{'file'}));
+				}
+				print "<div class=\"diff to_file\">$patch_line</div>\n";
 
-			#$patch_line =~ m/^+++/;
-			$file    = $diffinfo->{'to_file'};
-			$file  ||= $diffinfo->{'file'};
-			$file = $cgi->a({-href => href(action=>"blob", hash_base=>$hash,
-			                               hash=>$diffinfo->{'to_id'}, 
file_name=>$file),
-			                -class => "list"}, esc_path($file));
-			$patch_line =~ s|b/.*|b/$file|g;
-			print "<div class=\"diff to_file\">$patch_line</div>\n";
+			}
 
 			next LINE;
 		}
-		next LINE if $in_header;
 
 		print format_diff_line($patch_line);
 	}
-- 
1.4.3.4

^ permalink raw reply related

* [PATCH 0/2] gitweb: New improved patchset view
From: Jakub Narebski @ 2006-11-08 16:58 UTC (permalink / raw)
  To: git
In-Reply-To: <200611081150.07469.jnareb@gmail.com>

This series of patches is based on previous "[PATCH 0/2] Better unquoting
of git quoted filenames; esc_path to escape pathnames for display" series;
actually previous series was send because it is prerequisite of this series.

This series introduces new "feature", namely new commitdiff and blobdiff
view (new patchset view in short) BUT without this feature the accepted
"gitweb: Output also empty patches in "commitdiff" view" is of dubious value,
as it has not much sense without new patchset view.

Without "new improved patchset view" the empty patches are just that:
totally empty. It is new header and especially outputting extended header
information which makes outputting "empty" patches (with no diff)
in "commitdiff" view usefull. By "empty" patches I mean pure type change,
pure rename, pure copy, and type change with rename.


Shortlog:
 [PATCH 1/2] gitweb: New improved patchset view
 [PATCH 2/2] gitweb: New improved formatting of chunk header in diff

Diffstat:
 gitweb/gitweb.css  |   79 +++++++++++++++++---
 gitweb/gitweb.perl |  201 +++++++++++++++++++++++++++++++++++-----------------
 2 files changed, 203 insertions(+), 77 deletions(-)

-- 
Jakub Narebski
ShadeHawk on #git

^ permalink raw reply

* Re: Did anyone have trouble learning the idea of local vs. remote branches?
From: Wink Saville @ 2006-11-08 16:40 UTC (permalink / raw)
  To: Jakub Narebski; +Cc: git
In-Reply-To: <eis0v9$vug$1@sea.gmane.org>

Jakub Narebski wrote:
> Could you word-wrap your messages at some reasonable column, for example at
> 72 or 76-columns wide?

done

> Wink Saville wrote:
> 
>> As a newbie I'm confused, recently I attempted to get Andrew Morton's
>> -mm "tree".
> 
> Which is unusual git usage, as Andrew Morton uses Quilt/his own patch tools,
> and not git, if I remember correctly.
> 
>> It turns out the instructions were incorrect and Junio was 
>> kind enough to correct the mistake. But I for one am still confused.  
>>
>>   git-fetch is; "Download objects and a head from another repository"
>>
>> Fair enough and that make sense, but where does it go? Apparently it just
>> gets stored in the object database and a reference to it in "FETCH_HEAD".
>> Now what? Ok the documentation says:  
> 
> Objects gets stored into object database. Then (using FETCH_HEAD) heads
> of tracking branches gets updated (i.e. if there were some changes on
> branch 'master' in remote, the objects are downloaded, then head of local
> tracking branch corresponding to remote branch 'master', e.g. 'origin',
> gets updated with the value in 'master'; so called fast-forward case).
>  

OK, so fetch does more than just fetching, it also merges, confusing 
especially given the that the Description says otherwise.

I just searched git-fetch documentation and I see it mentioned under the 
<refspec> documentation. I read the words but why do I have to tell it 
what the source & destination. From my perspective the source is the url 
and the destination is my repository. So refspec doesn't make sense, of 
course it's my problem I'm not blaming git or the documentation. But as 
a newbie I'm confused.

As I continue to investigate the <refspec> documentation it mentions in 
the first "Note" that ".. rewound and rebased frequently, the a pull .." 
. OK, so why is "pull" mentioned here I'm not pulling I'm fetching. Of 
course if you go to the git-pull documentation we see the <refspec> 
repeated. Which maybe isn't surprising since pull is a fetch+merge. So I 
guess the confusing part is that fetch does do merging, even though it 
says it implies it doesn't.

>>   'The information is left for a later merge operation done by "git
>>   merge"' 
> 
> Or done by git pull. The information in FETCH_HEAD is for commit message
> in later merge (for example due to pull).
>  
>> Now in the case of fetching -mm apparently you don't do a merge, instead
>> the instructions now read: 
>>
>>   $ git-fetch \
>>     git://git.kernel.org/pub/scm/linux/kernel/git/smurf/linux-trees.git \
>>     tag v2.6.16-rc2-mm1  
>>   $ git-checkout -b local-v2.6.16-rc2-mm1 v2.6.16-rc2-mm1
> 
> Are you sure that it is 'tag' there?
> 

Yes, this is directly from Junio.

> BTW. you are actually encouraged to use "git fetch" and "git checkout",
> unless in scripts.
>
>> The git-fetch apparently gets "linux-trees.git" and places a reference to
>> it in a tag named 'v2.6.16-rc2-mm1'. Then the git-checkout, check's out
>> this tag to a new branch, there was no merge! This is confusing and makes
>> no sense to this newbie.   
> 
> The git-fetch fetches _from_ linux-trees.git repository. It fetches tag
> v2.6.16-rc2-mm1 (and its lineage, i.e. everything pointed by this tag,
> transitively) and stores it as local tag v2.6.16-rc2-mm1. You cannot
> checkout tag (you can't commit to tag), so you have to create new branch
> for your changes (or for checkout).
>  
>> Now lets take a quick look at the git-merge documentation "HOW MERGE
>> WORKS": 
>>
>> "A merge is always between the current HEAD and one or more remote branch
>> heads, and the index file must exactly match the tree of HEAD commit (i.e.
>> the contents of the last commit) when it happens. In other words, git-diff
>> --cached HEAD must report no changes."   
> 
> That's a bit untrue, because merge can happen between local branches too.
>  
>> Sorry, there is basically no information in those two sentences that makes
>> any sense to me. Take the first part, "between the current HEAD and one or
>> more remote branch heads". So apparently merges occur against the current
>> checkout branch, but I would guess the origin is also involved somehow? 
> 
> Current HEAD is current checked out branch. You merge current HEAD and one
> or more [remote] branch heads (in the pull case, those not marked
> not-for-merge in FETCH_HEAD), and place result in current branch.
> 
>> Secondly, what is the relationship between "remote branch heads" and
>> FETCH_HEAD? I see no mention of FETCH_HEAD or how it might be used
>> anywhere in the git-merge documentation.
> 
> FETCH_HEAD is low-lewel, not to be used by end-user (unless he/she wants to
> do something unusual).
> 

Then why mention it at all?

>> Then we come to "the index file 
>> must exactly match the tree HEAD commit", sorry but my question is how
>> could it not match? 
> 
> For example if you git-add'ed some files, but not committed the addition.

But if I've added some files, it would seem perfectly reasonable that 
git could still "merge" unless the new files conflicted with new files 
in the fetch.

> 
>> Obviously I don't understand how the index file is 
>> used, but I can say that adding "git-diff --cached HEAD must report no no
>> changes" adds nothing to the explanation, yet I'm sure it does mean
>> something to an expert.          
> 
> It adds command which you can use to check _why_ merge failed to run.
> 
>> It then goes onto say "it may fetch the objects from remote" I thought
>> that is what "fetch" does. 
> 
> IIRC this explanation is in git-pull(1). Pull in git is _fetch_ + merge.
>  

So a source of confusion is fetch also does merging/fast-forwarding, 
this is confusing. Fetch should fetch, merge should merge, pull should 
do both.

Another source of confusion is we start out with two branches after 
cloning _master_ & _origin_. Now if I create my own branch and check it 
out and then do a pull, what is going to be merged where and when?

I need to read, re-read and actually understand git-merge the "Grand 
Unified Merge Driver", I can see it's very powerful but with that power 
comes confusion.

At the moment my current situation is that I've cloned 2.6.19 done some 
pulls created some of my own branches and done a git-fetch on Andrew 
Morton's "tree". In .git/remotes I only have the file origin.

git-branch shows:

wink@winkc2d1:~/linux/linux-2.6$ git-branch
* ace
   local-2.6.19-rc4-mm2
   master
   origin
   w8

In tags I have:

wink@winkc2d1:~/linux/linux-2.6$ ls .git/refs/tags
ace-0.0.1     v2.6.13-rc3  v2.6.15-rc1  v2.6.16-rc5  v2.6.18-rc3
v2.6.11       v2.6.13-rc4  v2.6.15-rc2  v2.6.16-rc6  v2.6.18-rc4
v2.6.11-tree  v2.6.13-rc5  v2.6.15-rc3  v2.6.17      v2.6.18-rc5
v2.6.12       v2.6.13-rc6  v2.6.15-rc4  v2.6.17-rc1  v2.6.18-rc6
v2.6.12-rc2   v2.6.13-rc7  v2.6.15-rc5  v2.6.17-rc2  v2.6.18-rc7
v2.6.12-rc3   v2.6.14      v2.6.15-rc6  v2.6.17-rc3  v2.6.19-rc1
v2.6.12-rc4   v2.6.14-rc1  v2.6.15-rc7  v2.6.17-rc4  v2.6.19-rc2
v2.6.12-rc5   v2.6.14-rc2  v2.6.16      v2.6.17-rc5  v2.6.19-rc3
v2.6.12-rc6   v2.6.14-rc3  v2.6.16-rc1  v2.6.17-rc6  v2.6.19-rc4
v2.6.13       v2.6.14-rc4  v2.6.16-rc2  v2.6.18      v2.6.19-rc4-mm2
v2.6.13-rc1   v2.6.14-rc5  v2.6.16-rc3  v2.6.18-rc1
v2.6.13-rc2   v2.6.15      v2.6.16-rc4  v2.6.18-rc2

In remotes I have:

wink@winkc2d1:~/linux/linux-2.6$ ls .git/remotes
origin

So it would seem that I have no _remote_ connection to AM's tree and 
when I did the fetch it added objects which, from the perspective of 
linus's tree, is just a branch that I could have created by hand.

Now when I do my next git-pull from linu's tree what is going to happen 
with regards to my various branches if we assume that *ace is currently 
checked out.

Here is the current state:

origin			unchanged
master			unchanged
ace			locally modified and currently checked out
w8			locally modified
local-2.6.19-rc4-mm2	unchanged just a checkout of tag v2.6.19-rc4-mm2

Thanks,

Wink


^ permalink raw reply

* Shallow clone [Was Re: What's in git.git ]
From: Aneesh Kumar K.V @ 2006-11-08 16:40 UTC (permalink / raw)
  Cc: git
In-Reply-To: <Pine.LNX.4.63.0611072009220.2601@qynat.qvtvafvgr.pbz>

David Lang wrote:
> On Tue, 7 Nov 2006, Junio C Hamano wrote:
> 
>> [pu]
>>
>>  Johannes's shallow clone work now should rebase cleanly on top
>>  of 'master' although I haven't done so yet.  As he said
>>  himself the series is waiting for people who have needs for
>>  such a feature to raise hands.
> 
> I haven't been watching this recently, but if this is what I understand 
> it to be (the ability to get a partial repository from upstream and work 
> normally from there with the result of data-mineing tools sometimes 
> reporting 'that's part of the truncated history' if they hit the cutoff) 
> consider my hand raised.
> 
> there are a number of cases where I would be interested in following a 
> project as it moves forwards, but do not have the need to have the full 
> history (even with the good compression that a git pack provides, it's 
> still a significant amount of disk space and download time for large 
> projects)
> 

I am trying to test this feature. Is there a documentation .git/shallow some where. Atleast what those entries
mean ? I know in the mail johannes mentioned only core git will touch this file. But it should be ok to be 
descriptive like other files. (FETCH_HEAD)

-aneesh 

^ permalink raw reply

* Re: What's in git.git
From: Petr Baudis @ 2006-11-08 14:51 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git
In-Reply-To: <7v8ximwrm3.fsf@assigned-by-dhcp.cox.net>

>   By the way, do people mind if I start to rewind and rebase
>   'next' after every feature release (i.e. tagged release is
>   made after 'master')?  I do not feel a strong need for it, and
>   'git log --no-merges master..next' will show emptiness
>   eventually, but being able to restart from clean slate after a
>   release would be somewhat nice.

  It would be annoying for me since I can't mantain a long-term private
branch tracking next then (and I prefer next to master). I don't do that
right now but I've done that shortly in the past and it would be nice to
have that possibility in the future as well.

-- 
				Petr "Pasky" Baudis
Stuff: http://pasky.or.cz/
#!/bin/perl -sp0777i<X+d*lMLa^*lN%0]dsXx++lMlN/dsM0<j]dsj
$/=unpack('H*',$_);$_=`echo 16dio\U$k"SK$/SM$n\EsN0p[lN*1

^ permalink raw reply

* Re: win2k/cygwin cannot handle even moderately sized packs
From: Alex Riesen @ 2006-11-08 13:37 UTC (permalink / raw)
  To: Shawn Pearce; +Cc: Jakub Narebski, Junio C Hamano, git
In-Reply-To: <20061108051914.GB28498@spearce.org>

> > I couldn't help noticing that the interface to the packs data is
> > a bit complex:
> >
> >     unsigned char *use_pack(struct packed_git *p,
> >                           struct pack_window **window,
> >                           unsigned long offset,
> >                           unsigned int *left);
> >     void unuse_pack(struct pack_window **w);
> >
> > Or am I missing something very obvious, and something like this
> > is just not feasible for some reasons?
>
> The use counter.  Every time someone asks for a pointer into the
> pack they need to lock that window into memory to prevent us from
> garbage collecting it by unmapping it to make room for another
> window that the application needs.

I think the counters can be kept in struct packed_git somewhere. Given mmap
granularity, and the fact that not all of the pack is used in normal case
(and the granularity help us in the worst case) the memory used up by the
page counters shouldn't be too much.

> > I was almost about to move your code into unpack_object_header_gently,
> > but ... The header isn't that big, is it? It is variable in the pack,
> > but the implementation of the parser is at the moment restricted by
> > the type we use for object size (unsigned long for the particular
> > platform). For example:
>
> All true.  However what happens when the header spans two windows?
> Lets say I have the first 4 MiB mapped and the next 4 MiB mapped in
> a different window; these are not necessarily at the same locations
> within memory.  Now if an object header is split over these two
> then some bytes are at the end of the first window and the rest
> are at the start of the next window.

Assuming these are adjacent windows, we can just increment counters on the
all touched pages (at least the two together) and return the pointer into
the lowest page. Otherwise - time for garbage collection (why produce the
garbage at all, btw?) and remap.

> I can't just say "make sure we have at least X bytes available
> before starting to decode the header, as to do that in this case
> we'd have to unmap BOTH windows and remap a new one which keeps
> that very small header fully contiguous in memory.  That's thrashing
> the VM page tables for really no benefit.

You can't mmap less than a page, can you? So it's actually never a small
portion, but at least 4k on x86.

> > (BTW, current unpack_object_header_gently does not use it's len
> > argument to check if there actually is enough data to hold at least
> > minimal header. Is the size of mapped data checked for correctness
> > somewhere before?)
>
> Yes.  Somewhere.  I think we make sure there's at least 20 bytes
> in the pack remaining before we start to decode a header.  We must
> have at least 20 as that's the trailing SHA1 checksum of the entire
> pack. :-)


^ permalink raw reply

* Re: Did anyone have trouble learning the idea of local vs. remote branches?
From: Andreas Ericsson @ 2006-11-08 12:17 UTC (permalink / raw)
  To: git
In-Reply-To: <vpqbqnisegc.fsf@ecrins.imag.fr>

Matthieu Moy wrote:
> Shawn Pearce <spearce@spearce.org> writes:
> 
>> Today I was talking with someone that I collaborate with through
>> Git and they still seemed to not get the idea that all branches
>> in their repository are local, and that at least a 'git fetch'
>> is needed to update the local tracking branches to the version
>> in the central repository that we collaborate through.  And this
>> isn't the first time we've had such discussions.
> 
> To me, the biggest difficulty was to understand the vocubulary.

I had that same problem, although I started with git and came from CVS / 
SVN. I am sufficiently experienced with those two system to hope that I 
wouldn't come across any similarities at all, so I wasn't expecting any, 
so I didn't get too badly bitten.

The Documentation/glossary.txt file is a very good place to start 
reading, although I wouldn't object to it being re-arranged to have the 
terms described there pop up "in order of appearance", so to speak. I 
sent in a couple of patches to the glossary file whenever I encountered 
something in gittish that I didn't understand. Sometimes I had managed 
to guess the correct meaning and the patch got applied. In other cases I 
had it completely wrong and other, more gittish-fluent, people corrected 
the patches and amended the documentation that led to the confusion.

I think this is the only way to keep the docs alive and 
newcomer-friendly. Sadly, neither the maintainer nor the active 
contributors have newbie-eyes so we're relying on everyone who *are* new 
to git to help keep git easy for new people.


> And the git Vs cogito increased the confusion.
> 

I've found that too. It's a shame that some things can be done with git 
that isn't possible (or at least easy) with cogito and the other way 
around. The shared but divergent terminology doesn't exactly help 
either. Now I fear it's too late to do anything about it.

-- 
Andreas Ericsson                   andreas.ericsson@op5.se
OP5 AB                             www.op5.se

^ permalink raw reply

* [PATCH 1/2] gitweb: Better git-unquoting and gitweb-quoting of pathnames
From: Jakub Narebski @ 2006-11-08 10:48 UTC (permalink / raw)
  To: git
In-Reply-To: <200611081147.52952.jnareb@gmail.com>

Extend unquote subroutine, which unquotes quoted and escaped filenames
which git may return, to deal not only with octal char sequence
quoting, but also quoting ordinary characters including '\"' and '\\'
which are respectively quoted '"' and '\', and to deal also with
C escape sequences including '\t' for TAB and '\n' for LF.

Add esc_path subroutine for gitweb quoting and HTML escaping filenames
(currently it does equivalent of ls' --hide-control-chars, which means
showing undisplayable characters (including '\n' and '\t') as '?'
(question mark) character.  Convert gitweb to use esc_path instead of
simply esc_html to print pathnames.

Signed-off-by: Jakub Narebski <jnareb@gmail.com>
---
I hope I catched all the places where esc_html should be replaced by
esc_path.

 gitweb/gitweb.perl |   72 ++++++++++++++++++++++++++++++++++++++-------------
 1 files changed, 53 insertions(+), 19 deletions(-)

diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl
index c46629f..32926f9 100755
--- a/gitweb/gitweb.perl
+++ b/gitweb/gitweb.perl
@@ -584,12 +584,46 @@ sub esc_html ($;%) {
 	return $str;
 }
 
+# quote control characters and escape filename to HTML
+sub esc_path {
+	my $str = shift;
+	$str = esc_html($str);
+	$str =~ s/[[:cntrl:]]/?/g; # like --hide-control-chars in ls
+	return $str;
+}
+
 # git may return quoted and escaped filenames
 sub unquote {
 	my $str = shift;
+
+	sub unq {
+		my $seq = shift;
+		my %es = ( # character escape codes, aka escape sequences
+			't' => "\t",   # tab            (HT, TAB)
+			'n' => "\n",   # newline        (NL)
+			'r' => "\r",   # return         (CR)
+			'f' => "\f",   # form feed      (FF)
+			'b' => "\b",   # backspace      (BS)
+			'a' => "\a",   # alarm (bell)   (BEL)
+			'e' => "\e",   # escape         (ESC)
+			'v' => "\013", # vertical tab   (VT)
+		);
+
+		if ($seq =~ m/^[0-7]{1,3}$/) {
+			# octal char sequence
+			return chr(oct($seq));
+		} elsif (exists $es{$seq}) {
+			# C escape sequence, aka character escape code
+			return $es{$seq}
+		}
+		# quoted ordinary character
+		return $seq;
+	}
+
 	if ($str =~ m/^"(.*)"$/) {
+		# needs unquoting
 		$str = $1;
-		$str =~ s/\\([0-7]{1,3})/chr(oct($1))/eg;
+		$str =~ s/\\([^0-7]|[0-7]{1,3})/unq($1)/eg;
 	}
 	return $str;
 }
@@ -1520,7 +1554,7 @@ sub git_header_html {
 		if (defined $action) {
 			$title .= "/$action";
 			if (defined $file_name) {
-				$title .= " - " . esc_html($file_name);
+				$title .= " - " . esc_path($file_name);
 				if ($action eq "tree" && $file_name !~ m|/$|) {
 					$title .= "/";
 				}
@@ -1791,20 +1825,20 @@ sub git_print_page_path {
 			$fullname .= ($fullname ? '/' : '') . $dir;
 			print $cgi->a({-href => href(action=>"tree", file_name=>$fullname,
 			                             hash_base=>$hb),
-			              -title => $fullname}, esc_html($dir));
+			              -title => $fullname}, esc_path($dir));
 			print " / ";
 		}
 		if (defined $type && $type eq 'blob') {
 			print $cgi->a({-href => href(action=>"blob_plain", file_name=>$file_name,
 			                             hash_base=>$hb),
-			              -title => $name}, esc_html($basename));
+			              -title => $name}, esc_path($basename));
 		} elsif (defined $type && $type eq 'tree') {
 			print $cgi->a({-href => href(action=>"tree", file_name=>$file_name,
 			                             hash_base=>$hb),
-			              -title => $name}, esc_html($basename));
+			              -title => $name}, esc_path($basename));
 			print " / ";
 		} else {
-			print esc_html($basename);
+			print esc_path($basename);
 		}
 	}
 	print "<br/></div>\n";
@@ -1876,7 +1910,7 @@ sub git_print_tree_entry {
 		print "<td class=\"list\">" .
 			$cgi->a({-href => href(action=>"blob", hash=>$t->{'hash'},
 			                       file_name=>"$basedir$t->{'name'}", %base_key),
-			        -class => "list"}, esc_html($t->{'name'})) . "</td>\n";
+			        -class => "list"}, esc_path($t->{'name'})) . "</td>\n";
 		print "<td class=\"link\">";
 		print $cgi->a({-href => href(action=>"blob", hash=>$t->{'hash'},
 					     file_name=>"$basedir$t->{'name'}", %base_key)},
@@ -1903,7 +1937,7 @@ sub git_print_tree_entry {
 		print "<td class=\"list\">";
 		print $cgi->a({-href => href(action=>"tree", hash=>$t->{'hash'},
 		                             file_name=>"$basedir$t->{'name'}", %base_key)},
-		              esc_html($t->{'name'}));
+		              esc_path($t->{'name'}));
 		print "</td>\n";
 		print "<td class=\"link\">";
 		print $cgi->a({-href => href(action=>"tree", hash=>$t->{'hash'},
@@ -1968,7 +2002,7 @@ sub git_difftree_body {
 			print "<td>";
 			print $cgi->a({-href => href(action=>"blob", hash=>$diff{'to_id'},
 			                             hash_base=>$hash, file_name=>$diff{'file'}),
-			              -class => "list"}, esc_html($diff{'file'}));
+			              -class => "list"}, esc_path($diff{'file'}));
 			print "</td>\n";
 			print "<td>$mode_chng</td>\n";
 			print "<td class=\"link\">";
@@ -1984,7 +2018,7 @@ sub git_difftree_body {
 			print "<td>";
 			print $cgi->a({-href => href(action=>"blob", hash=>$diff{'from_id'},
 			                             hash_base=>$parent, file_name=>$diff{'file'}),
-			               -class => "list"}, esc_html($diff{'file'}));
+			               -class => "list"}, esc_path($diff{'file'}));
 			print "</td>\n";
 			print "<td>$mode_chng</td>\n";
 			print "<td class=\"link\">";
@@ -2024,7 +2058,7 @@ sub git_difftree_body {
 			print "<td>";
 			print $cgi->a({-href => href(action=>"blob", hash=>$diff{'to_id'},
 			                             hash_base=>$hash, file_name=>$diff{'file'}),
-			              -class => "list"}, esc_html($diff{'file'}));
+			              -class => "list"}, esc_path($diff{'file'}));
 			print "</td>\n";
 			print "<td>$mode_chnge</td>\n";
 			print "<td class=\"link\">";
@@ -2064,11 +2098,11 @@ sub git_difftree_body {
 			print "<td>" .
 			      $cgi->a({-href => href(action=>"blob", hash_base=>$hash,
 			                             hash=>$diff{'to_id'}, file_name=>$diff{'to_file'}),
-			              -class => "list"}, esc_html($diff{'to_file'})) . "</td>\n" .
+			              -class => "list"}, esc_path($diff{'to_file'})) . "</td>\n" .
 			      "<td><span class=\"file_status $nstatus\">[$nstatus from " .
 			      $cgi->a({-href => href(action=>"blob", hash_base=>$parent,
 			                             hash=>$diff{'from_id'}, file_name=>$diff{'from_file'}),
-			              -class => "list"}, esc_html($diff{'from_file'})) .
+			              -class => "list"}, esc_path($diff{'from_file'})) .
 			      " with " . (int $diff{'similarity'}) . "% similarity$mode_chng]</span></td>\n" .
 			      "<td class=\"link\">";
 			if ($action eq 'commitdiff') {
@@ -2191,7 +2225,7 @@ sub git_patchset_body {
 			$file  ||= $diffinfo->{'file'};
 			$file = $cgi->a({-href => href(action=>"blob", hash_base=>$hash_parent,
 			                               hash=>$diffinfo->{'from_id'}, file_name=>$file),
-			                -class => "list"}, esc_html($file));
+			                -class => "list"}, esc_path($file));
 			$patch_line =~ s|a/.*$|a/$file|g;
 			print "<div class=\"diff from_file\">$patch_line</div>\n";
 
@@ -2203,7 +2237,7 @@ sub git_patchset_body {
 			$file  ||= $diffinfo->{'file'};
 			$file = $cgi->a({-href => href(action=>"blob", hash_base=>$hash,
 			                               hash=>$diffinfo->{'to_id'}, file_name=>$file),
-			                -class => "list"}, esc_html($file));
+			                -class => "list"}, esc_path($file));
 			$patch_line =~ s|b/.*|b/$file|g;
 			print "<div class=\"diff to_file\">$patch_line</div>\n";
 
@@ -3521,8 +3555,8 @@ sub git_blobdiff {
 
 	} else {
 		while (my $line = <$fd>) {
-			$line =~ s!a/($hash|$hash_parent)!'a/'.esc_html($diffinfo{'from_file'})!eg;
-			$line =~ s!b/($hash|$hash_parent)!'b/'.esc_html($diffinfo{'to_file'})!eg;
+			$line =~ s!a/($hash|$hash_parent)!'a/'.esc_path($diffinfo{'from_file'})!eg;
+			$line =~ s!b/($hash|$hash_parent)!'b/'.esc_path($diffinfo{'to_file'})!eg;
 
 			print $line;
 
@@ -3879,7 +3913,7 @@ sub git_search {
 						print $cgi->a({-href => href(action=>"blob", hash_base=>$co{'id'},
 						                             hash=>$set{'id'}, file_name=>$set{'file'}),
 						              -class => "list"},
-						              "<span class=\"match\">" . esc_html($set{'file'}) . "</span>") .
+						              "<span class=\"match\">" . esc_path($set{'file'}) . "</span>") .
 						      "<br/>\n";
 					}
 					print "</td>\n" .
@@ -4014,7 +4048,7 @@ XML
 			if (!($line =~ m/^:([0-7]{6}) ([0-7]{6}) ([0-9a-fA-F]{40}) ([0-9a-fA-F]{40}) (.)([0-9]{0,3})\t(.*)$/)) {
 				next;
 			}
-			my $file = esc_html(unquote($7));
+			my $file = esc_path(unquote($7));
 			$file = to_utf8($file);
 			print "$file<br/>\n";
 		}
-- 
1.4.3.4

^ permalink raw reply related

* [PATCH 2/2] gitweb: Use character or octal escape codes (and add span.cntrl) in esc_path
From: Jakub Narebski @ 2006-11-08 10:50 UTC (permalink / raw)
  To: git
In-Reply-To: <200611081147.52952.jnareb@gmail.com>

Instead of simply hiding control characters in esc_path by replacing
them with '?', use Character Escape Codes (CEC) i.e. alphabetic
backslash sequences like those found in C programming language and
many other languages influenced by it, such as Java and Perl.  If
control characted doesn't have corresponding character escape code,
use octal char sequence to escape it.

Additionally use 'span' element with 'cntrl' attribute to mark escaped
control characters. Add style for span.cntrl in the CSS.

Below there is alternative quoting using Unicode Printable
Representation (PR), i.e. replace control characters with appropriate
Unicode Control Pictures U+2400 - U+243F (9216 - 9279), the Unicode
characters reserved for representing control characters when it is
necessary to print or display them:

sub esc_path {
	my $str = shift;
	$str = esc_html($str);
	$str =~ s!([[:cntrl:]])!sprintf('<span class="cntrl">&#%04d;</span>', 0x2400+ord($1))!eg;
	return $str;
}

Signed-off-by: Jakub Narebski <jnareb@gmail.com>
---
The styling (span.cntrl style) isn't best, I agree.

 gitweb/gitweb.css  |    7 +++++++
 gitweb/gitweb.perl |   25 ++++++++++++++++++++++++-
 2 files changed, 31 insertions(+), 1 deletions(-)

diff --git a/gitweb/gitweb.css b/gitweb/gitweb.css
index 0eda982..e19e6bc 100644
--- a/gitweb/gitweb.css
+++ b/gitweb/gitweb.css
@@ -16,6 +16,13 @@ a:hover, a:visited, a:active {
 	color: #880000;
 }
 
+span.cntrl {
+	border: dashed #aaaaaa;
+	border-width: 1px;
+	padding: 0px 2px 0px 2px;
+	margin:  0px 2px 0px 2px;
+}
+
 img.logo {
 	float: right;
 	border-width: 0px;
diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl
index 32926f9..c9b16b5 100755
--- a/gitweb/gitweb.perl
+++ b/gitweb/gitweb.perl
@@ -587,8 +587,31 @@ sub esc_html ($;%) {
 # quote control characters and escape filename to HTML
 sub esc_path {
 	my $str = shift;
+
+	sub quot {
+		my $seq = shift;
+		my %es = ( # character escape codes, aka escape sequences
+			"\t" => '\t',   # tab            (HT, TAB)
+			"\n" => '\n',   # newline        (NL)
+			"\r" => '\r',   # return         (CR)
+			"\f" => '\f',   # form feed      (FF)
+			"\b" => '\b',   # backspace      (BS)
+			"\a" => '\a',   # alarm (bell)   (BEL)
+			"\e" => '\e',   # escape         (ESC)
+			"\013" => '\v', # vertical tab   (VT)
+			"\000" => '\0', # null character (NUL)
+		);
+
+		if (exists $es{$seq}) {
+			# C escape sequence, aka character escape code
+			return $es{$seq};
+		}
+		# octal char sequence
+		return sprintf('\%03o', ord($seq));
+	}
+
 	$str = esc_html($str);
-	$str =~ s/[[:cntrl:]]/?/g; # like --hide-control-chars in ls
+	$str =~ s!([[:cntrl:]])!'<span class="cntrl">' . quot($1) . '</span>'!eg;
 	return $str;
 }
 
-- 
1.4.3.4

^ permalink raw reply related

* [PATCH 0/2] Better unquoting of git quoted filenames; esc_path to escape pathnames for display
From: Jakub Narebski @ 2006-11-08 10:47 UTC (permalink / raw)
  To: git

This series fixes unquote so that it can deal with alphabetic escape
sequences like '\n' and '\t', and escaped literal characters like '\"'
and '\\', and adds esc_path do deal with the fact that unquoted 
filenames can now contain control characters, not suitable for HTML.
Previous version of unquote was broken in that it did only octal
escape sequence unquoting, and could leave filename only partially
unquoted.

First patch adds minimal esc_path, second improves esc_path to final
version.

Shortlog:
 [PATCH 1/2] gitweb: Better git-unquoting and gitweb-quoting of pathnames
 [PATCH 2/2] gitweb: Use character or octal escape codes (and add span.cntrl) in esc_path

Diffstat:
 gitweb/gitweb.css  |    7 ++++
 gitweb/gitweb.perl |   95 +++++++++++++++++++++++++++++++++++++++++----------
 2 files changed, 83 insertions(+), 19 deletions(-)

-- 
Jakub Narebski

^ permalink raw reply

* Re: [PATCH] Add a MIME-Version header to e-mails
From: Catalin Marinas @ 2006-11-08 10:12 UTC (permalink / raw)
  To: Karl Hasselström; +Cc: git
In-Reply-To: <20061108100103.GA18117@diana.vm.bytemark.co.uk>

On 08/11/06, Karl Hasselström <kha@treskal.com> wrote:
> On 2006-11-08 09:41:33 +0000, Catalin Marinas wrote:
> > It would be great if you can run a test script. I've been thinking
> > more of an "import" test that also checks both the "export" and "mail"
> > commands.
>
> I didn't originally plan to thest the actual e-mail sending, but now
> that I think of it, a simple script listening on a random port,
> pretending to be an SMTP daemon, should be quite simple to set up.

I'm not sure it's worth the hassle. You could just generate an mbox
file with "mail" and import it with "import --mbox" (it will hopefully
be ready this week). Problems with SMTP would be noticed quickly
anyway.

-- 

^ permalink raw reply

* Re: [PATCH] Add a MIME-Version header to e-mails
From: Karl Hasselström @ 2006-11-08 10:01 UTC (permalink / raw)
  To: Catalin Marinas; +Cc: git
In-Reply-To: <b0943d9e0611080141y3751039v37b0289147237e4f@mail.gmail.com>

On 2006-11-08 09:41:33 +0000, Catalin Marinas wrote:

> On 08/11/06, Karl Hasselström <kha@treskal.com> wrote:
>
> > On 2006-11-07 19:09:06 +0000, Catalin Marinas wrote:
> >
> > > I re-implemented parts of the mail and import commands
> > > (inspiring from your patches). They now use the email Python
> > > package. The mail command encodes the body to 7 or 8bit
> > > depending on non-ascii characters.
> >
> > Even though it turned out to be possible to use 8bit always?
>
> I just let the Python email package to the encoding and it first
> tries pure ascii and switches to 8bit if this fails.

Ah, OK, I misread you. This is precisely what I wanted.

> It can also do QP or base64 encodings (if someone complains of an
> old SMTP server, maybe I'll add a config option to force QP body).

Yes, but let's hope we don't have to. :-) And if we do have to, we
should probably autodetect it from the SMTP dialog as Linus explained
(or rather, we should hope that the library can do this for us).

> > > I still have to write a test script but my simple tests showed
> > > that it works. Please let me know if there is anything wrong
> > > (especially with the QP-encoding of the mail headers).
> >
> > I won't have time to check this out today (in fact, it may have to
> > wait until the weekend). But when I do check it out, I might have
> > time to write that test, so please holler if you start working on
> > that.
>
> It would be great if you can run a test script. I've been thinking
> more of an "import" test that also checks both the "export" and "mail"
> commands.

I was thinking along these lines too; first make sure the importer
works, by feeding it a number of hard-coded patches in different
formats, and then make sure that the importer can read what the
exporter produces. (With "exporter" meaning both "stg export" and "stg
mail".)

I didn't originally plan to thest the actual e-mail sending, but now
that I think of it, a simple script listening on a random port,
pretending to be an SMTP daemon, should be quite simple to set up.

> BTW, I'll try to add support for mbox importing which is pretty easy
> with the email package.

Sounds good. If you do it in time, I'll write a test for that too. ;-)

-- 
Karl Hasselström, kha@treskal.com

^ permalink raw reply

* Re: [PATCH] Add a MIME-Version header to e-mails
From: Catalin Marinas @ 2006-11-08  9:41 UTC (permalink / raw)
  To: Karl Hasselström; +Cc: git
In-Reply-To: <20061108084038.GA3164@diana.vm.bytemark.co.uk>

On 08/11/06, Karl Hasselström <kha@treskal.com> wrote:
> On 2006-11-07 19:09:06 +0000, Catalin Marinas wrote:
>
> > I re-implemented parts of the mail and import commands (inspiring
> > from your patches). They now use the email Python package. The mail
> > command encodes the body to 7 or 8bit depending on non-ascii
> > characters.
>
> Even though it turned out to be possible to use 8bit always?

I just let the Python email package to the encoding and it first tries
pure ascii and switches to 8bit if this fails. This package
automatically adds the proper e-mail headers based on the encoding
type. It can also do QP or base64 encodings (if someone complains of
an old SMTP server, maybe I'll add a config option to force QP body).

> > I still have to write a test script but my simple tests showed that
> > it works. Please let me know if there is anything wrong (especially
> > with the QP-encoding of the mail headers).
>
> I won't have time to check this out today (in fact, it may have to
> wait until the weekend). But when I do check it out, I might have time
> to write that test, so please holler if you start working on that.

It would be great if you can run a test script. I've been thinking
more of an "import" test that also checks both the "export" and "mail"
commands. BTW, I'll try to add support for mbox importing which is
pretty easy with the email package.

-- 

^ permalink raw reply

* Re: [PATCH] Add a MIME-Version header to e-mails
From: Karl Hasselström @ 2006-11-08  8:40 UTC (permalink / raw)
  To: Catalin Marinas; +Cc: git
In-Reply-To: <b0943d9e0611071109w584f4f7fv3ba1b7dbd9413717@mail.gmail.com>

On 2006-11-07 19:09:06 +0000, Catalin Marinas wrote:

> I re-implemented parts of the mail and import commands (inspiring
> from your patches). They now use the email Python package. The mail
> command encodes the body to 7 or 8bit depending on non-ascii
> characters.

Even though it turned out to be possible to use 8bit always?

> The headers are QP-encoded.

Strictly speaking, it's rfc2047-encoded. I think the options are QP
and base64.

> The import command can decode messages properly and can also handle
> multipart e-mails.

Goodie.

> I still have to write a test script but my simple tests showed that
> it works. Please let me know if there is anything wrong (especially
> with the QP-encoding of the mail headers).

I won't have time to check this out today (in fact, it may have to
wait until the weekend). But when I do check it out, I might have time
to write that test, so please holler if you start working on that.

-- 
Karl Hasselström, kha@treskal.com

^ permalink raw reply

* Re: What's in git.git
From: Junio C Hamano @ 2006-11-08  8:26 UTC (permalink / raw)
  To: git; +Cc: jnareb
In-Reply-To: <eis2m4$3i6$1@sea.gmane.org>

Jakub Narebski <jnareb@gmail.com> writes:

> Junio C Hamano wrote:
>
>> [master]
>> 
>>   Three topics that have been cooking in 'next' have been
>>   merged, I've tagged the tip as v1.4.4-rc1.
>
> By the way, tag v1.4.4-rc1 has "GIT 1.4.4-rc1" as title, while the commit it
> points to, v1.4.4-rc1^{} has "GIT 1.4.3-rc1" as a title.

Yeah, sometimes I make typoes.  Not a news X-<.

^ permalink raw reply

* Re: What's in git.git
From: Junio C Hamano @ 2006-11-08  7:59 UTC (permalink / raw)
  To: Jakub Narebski; +Cc: git
In-Reply-To: <eis1j6$vug$2@sea.gmane.org>

Jakub Narebski <jnareb@gmail.com> writes:

> Junio C Hamano wrote:
>
>>    Jakub Narebski (4):
> [...]
>>       gitweb: Output also empty patches in "commitdiff" view
>
> I think that this patch is a bit premature. Without "new improved patchset
> view" the empty patches are just that: totally empty. It is new header and
> especially outputting extended header information which makes outputting
> "empty" patches (with no diff) in "commitdiff" view usefull. By "empty"
> patches I mean pure type change, pure rename, pure copy and type change and
> rename.
>
> The "new improved patchset view" is prepared to send in two stages...

At least this does not break the page even without these two
follow-ups.  If the follow-ups come in time and do not break the
page, they are very welcome post -rc1 fixes to have before the
final release.  On the other hand, even if they don't, it's not
the end of the world ;-).


^ permalink raw reply

* Re: What's in git.git
From: Jakub Narebski @ 2006-11-08  7:58 UTC (permalink / raw)
  To: git
In-Reply-To: <7v8ximwrm3.fsf@assigned-by-dhcp.cox.net>

Junio C Hamano wrote:

> [master]
> 
>   Three topics that have been cooking in 'next' have been
>   merged, I've tagged the tip as v1.4.4-rc1.

By the way, tag v1.4.4-rc1 has "GIT 1.4.4-rc1" as title, while the commit it
points to, v1.4.4-rc1^{} has "GIT 1.4.3-rc1" as a title.
-- 
Jakub Narebski
Warsaw, Poland
ShadeHawk on #git


^ permalink raw reply

* Re: What's in git.git
From: Jakub Narebski @ 2006-11-08  7:40 UTC (permalink / raw)
  To: git
In-Reply-To: <7v8ximwrm3.fsf@assigned-by-dhcp.cox.net>

Junio C Hamano wrote:

>    Jakub Narebski (4):
[...]
>       gitweb: Output also empty patches in "commitdiff" view

I think that this patch is a bit premature. Without "new improved patchset
view" the empty patches are just that: totally empty. It is new header and
especially outputting extended header information which makes outputting
"empty" patches (with no diff) in "commitdiff" view usefull. By "empty"
patches I mean pure type change, pure rename, pure copy and type change and
rename.

The "new improved patchset view" is prepared to send in two stages: updated
filename quoting/unquoting series (two patches: unescape + minimal
esc_path; esc_path with span.cntrl and backslash sequence quoting), and
"new improved patchset view" (three patches originally, two remains: using
"git diff" header and extended git diff headers; output and link also to
patches with empty diff; improved formatting of chunk header).
-- 
Jakub Narebski
Warsaw, Poland
ShadeHawk on #git


^ permalink raw reply

* Re: Did anyone have trouble learning the idea of local vs. remote branches?
From: Jakub Narebski @ 2006-11-08  7:29 UTC (permalink / raw)
  To: git
In-Reply-To: <455169D1.8060408@saville.com>

Could you word-wrap your messages at some reasonable column, for example at
72 or 76-columns wide?

Wink Saville wrote:

> As a newbie I'm confused, recently I attempted to get Andrew Morton's
> -mm "tree".

Which is unusual git usage, as Andrew Morton uses Quilt/his own patch tools,
and not git, if I remember correctly.

> It turns out the instructions were incorrect and Junio was 
> kind enough to correct the mistake. But I for one am still confused.  
>
>   git-fetch is; "Download objects and a head from another repository"
> 
> Fair enough and that make sense, but where does it go? Apparently it just
> gets stored in the object database and a reference to it in "FETCH_HEAD".
> Now what? Ok the documentation says:  

Objects gets stored into object database. Then (using FETCH_HEAD) heads
of tracking branches gets updated (i.e. if there were some changes on
branch 'master' in remote, the objects are downloaded, then head of local
tracking branch corresponding to remote branch 'master', e.g. 'origin',
gets updated with the value in 'master'; so called fast-forward case).
 
>   'The information is left for a later merge operation done by "git
>   merge"' 

Or done by git pull. The information in FETCH_HEAD is for commit message
in later merge (for example due to pull).
 
> Now in the case of fetching -mm apparently you don't do a merge, instead
> the instructions now read: 
> 
>   $ git-fetch \
>     git://git.kernel.org/pub/scm/linux/kernel/git/smurf/linux-trees.git \
>     tag v2.6.16-rc2-mm1  
>   $ git-checkout -b local-v2.6.16-rc2-mm1 v2.6.16-rc2-mm1

Are you sure that it is 'tag' there?

BTW. you are actually encouraged to use "git fetch" and "git checkout",
unless in scripts.

> The git-fetch apparently gets "linux-trees.git" and places a reference to
> it in a tag named 'v2.6.16-rc2-mm1'. Then the git-checkout, check's out
> this tag to a new branch, there was no merge! This is confusing and makes
> no sense to this newbie.   

The git-fetch fetches _from_ linux-trees.git repository. It fetches tag
v2.6.16-rc2-mm1 (and its lineage, i.e. everything pointed by this tag,
transitively) and stores it as local tag v2.6.16-rc2-mm1. You cannot
checkout tag (you can't commit to tag), so you have to create new branch
for your changes (or for checkout).
 
> Now lets take a quick look at the git-merge documentation "HOW MERGE
> WORKS": 
> 
> "A merge is always between the current HEAD and one or more remote branch
> heads, and the index file must exactly match the tree of HEAD commit (i.e.
> the contents of the last commit) when it happens. In other words, git-diff
> --cached HEAD must report no changes."   

That's a bit untrue, because merge can happen between local branches too.
 
> Sorry, there is basically no information in those two sentences that makes
> any sense to me. Take the first part, "between the current HEAD and one or
> more remote branch heads". So apparently merges occur against the current
> checkout branch, but I would guess the origin is also involved somehow? 

Current HEAD is current checked out branch. You merge current HEAD and one
or more [remote] branch heads (in the pull case, those not marked
not-for-merge in FETCH_HEAD), and place result in current branch.

> Secondly, what is the relationship between "remote branch heads" and
> FETCH_HEAD? I see no mention of FETCH_HEAD or how it might be used
> anywhere in the git-merge documentation.

FETCH_HEAD is low-lewel, not to be used by end-user (unless he/she wants to
do something unusual).

> Then we come to "the index file 
> must exactly match the tree HEAD commit", sorry but my question is how
> could it not match? 

For example if you git-add'ed some files, but not committed the addition.

> Obviously I don't understand how the index file is 
> used, but I can say that adding "git-diff --cached HEAD must report no no
> changes" adds nothing to the explanation, yet I'm sure it does mean
> something to an expert.          

It adds command which you can use to check _why_ merge failed to run.

> It then goes onto say "it may fetch the objects from remote" I thought
> that is what "fetch" does. 

IIRC this explanation is in git-pull(1). Pull in git is _fetch_ + merge.
 
-- 
Jakub Narebski
Warsaw, Poland
ShadeHawk on #git


^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox