Posts Tagged v0.9

v0.9 Release Complete

All the goals for my v0.9 release have been accomplished and thus another release comes to an end. Looking back I ended up using quite a bit of jquery to fix my bugs. In the process I learnt some new things about the library that I didn’t know beforehand, such as how $(document).ready() works. The guys over at jquery have definitely done some good work.

Files touched

This patch had bitrotted as the pushlog had gone through a variety of changes since I had submitted it way back in 2008. Now, it is up to date and raring to go. I will most probably have another iteration for this patch though, where I add expand/collapse functionality to it. Although, I’ll have to get clearance from ted first though.

Changeset UI

Ted gave me an r- review since he didn’t like that I was removing what the user had entered in the text boxes if another item was selected from the drop down list. Also, he wanted the drop down list to remember which query type was last executed. I’ve managed to get both these features working and I also altered the code to take advantage of jquery, which is now available in hg_templates.

Line breaks turned into spaces

This was the new bug that I tackled this release. First of all I wanted to keep the line breaks instead of have them turned into spaces. I managed to do that. Next, I had to implement expand/collapse functionality for any commit messages that had more than one line break. Since I had experience doing this with another bug; I quickly managed to get this functionality working.

The following are the important links for this release:

The patches have been posted to their respective bug pages. Please view the project page for further details.

, , ,

1 Comment

v0.9 Release - Fix for the Line Break bug

In my previous blog post I explained the line break bug and how I would go about fixing it. I’ve managed to get the functionality up and running now. Lets have a look at the code:

// ellipsis for multi-line desc messages
$('.desc').each(function (i) {
  if($(this).html().indexOf("\n") != -1) {
    $(this).html($(this).html().replace(/\n/g, "
"));
    $(this).html(createEllipsis($(this).html(), ($(this).attr("class")).match(/id\d+/) + i));
    $('.hide').hide();
  }
});
$('.ellipsisexpand').click(function () {
  var pushid = $(this).attr("class");
  pushid = 'span.' + pushid.match(/id\d+/);
  $(pushid).toggle();
  return false;
});
function createEllipsis(html, pushid) {
  return html.substring(0, html.indexOf(""))
    + "<a class="\&quot;ellipsisexpand" href="\">[...]</a><span class="\&quot;hide">"
    + html.substring(html.indexOf(""), html.length)
    + "</span>";
}

The map file:

<strong class="desc id#id#">#author|person# — #desc|strip|escape|buglink#</strong>

When using jquery you want to keep all your functionality within the $(document).ready function, which is what I have done. So, in the map file I gave the strong tag that contains the commit message a new class, called desc (see above). Then, I loop through each tag containing a class called desc with the code on line 36. Within the loop I replace all occurances of ‘\n’ with ‘<br/>’.  Next I call createEllipsis() (line  39). This function rewrites the html within the strong tag to include an ellipsis link and puts all the lines that will get expanded/collapsed in a different span tag. Lastly, line 40 hides everything that should be hidden.

Next I have a click handler that expands/collapses any span tag with the class name ‘hide’. Within this function, I also uniquely identify which span tag to toggle. This is needed because there are can be more than one span tag with the class name, ‘hide’ on any given page. I set the pushid as one of the class names to uniquely identify each span tag. Thus, each span tag that should be hidden will have two class names, hide and the pushid. See the results below:

Collapsed Example

Expanded Example

,

No Comments

v0.9 Release - Contemplating the Implementation for the Line Break bug

As one of my goals for this release I wanted to take on a new bug. Now, the problem is that if there are line breaks in the commit message the pushlog will just turn them into spaces. Thus the message will become one big clump of text, which doesn’t look good.

The goal is to only show the very first line of the commit message if it has any line breaks in it. Then have an ellipsis link at the end that the user can click to expand/collapse the rest of the message. Also, when the message is expanded the line breaks should be displayed properly. For example:

Current Implementation

I am trying to fix a new bug 1) I will use jquery 2) I will finish it soon 3) 2 + 2 is 4

New Implementation while collapsed

I am trying to fix a new bug [...]

New Implementation while expanded

I am trying to fix a new bug [...]
1) I will use jquery
2) I will finish it soon
3) 2 + 2 is 4 or is it 22?

I will probably keep all the new code on the client side, implemented using jquery. Right now the line breaks are turned into spaces because they use the ‘\n’ character instead of using ‘<br/>’. I want to change all the line breaks to ‘<br />’ and then add an ellipsis link to all the commit messages that need it.

I’ve added expand/collapse functionality to the pushlog before so this shouldn’t be very hard to do. Look out for my next blog post explaining my implementation.

,

No Comments

v0.9 Release - Implementing changes to the Changset Query UI

In my goals blog post I outlined my revised plans for the changeset query UI. I wanted to make the use of jquery now that the library has been added to the repo. Also, the textbox value that the user enters for a query shouldn’t be removed or changed. Furthermore, I wanted to add the 3rd query supported by the pushlog, which takes in two pushids. Lastly, I also wanted the UI to remember the previously executed query (I forgot to specify this in my goals post). So, for example if I make a changeset query and the results are displayed, the selected item on the drop down should still be a changeset. I believe this is what ted wanted, if I understood him correctly.

Previous Implementation

Let me show you the old code to put things into perspective so that it’s easier to visualize what changes I have made:

function changeQueryType() 
{
  var queryType = document.getElementById("querytype");
  var fromBox = document.getElementById("from");
  var toBox = document.getElementById("to");
  if(queryType.value == "changeset") {
    fromBox.name = "fromchange";
    fromBox.value="#fromchange|escape#";
    toBox.name = "tochange";
    toBox.value="#tochange|escape#";
  } else {
    fromBox.name = "startdate";
    fromBox.value="#startdate|escape#";
    toBox.name = "enddate";
    toBox.value="#enddate|escape#";
}
<form action="{url}pushloghtml">
<div class="search">
<select id="querytype" onchange="changeQueryType()">
<option value="date">Date</option>
<option value="changeset">Changeset</option>
</select>&nbsp;&nbsp;&nbsp;
From:
<input id="from" type="text" name="startdate"  value="#startdate|escape#"/>
To:
<input id="to" type="text"name="enddate"  value="#enddate|escape#"/>
<input type="submit" value="Search"/>
</div>
</form>

Moving to jquery

As I mentioned before we are now using jquery in hg_templates. This is a great move as I love using this library. I’m still learning new things about it every time I try something. Here is what my code looks like with the jquery changes:

35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
// remember the previously selected query
var queryString = window.top.location.search.substring(1);
if(queryString != "") {
  if(queryString.indexOf("startdate") != -1)
    $(".querytype option[value='date']").attr('selected', 'selected');
  else if(queryString.indexOf("fromchange") != -1)
    $(".querytype option[value='changeset']").attr('selected', 'selected');
  else if(queryString.indexOf("startID") != -1)
    $(".querytype option[value='pushid']").attr('selected', 'selected');
}
//decide what query to execute
$('.querytype').change(function () {
  if($('.querytype option:selected').attr('value') == 'date') {
    $('.from').attr('name', 'startdate');
    $('.to').attr('name', 'enddate');
  }
  else if($('.querytype option:selected').attr('value') == 'changeset') {
    $('.from').attr('name', 'fromchange');
    $('.to').attr('name', 'tochange');
  }
  else {
    $('.from').attr('name', 'startID');
    $('.to').attr('name', 'endID');
  }
});
70
71
72
73
74
75
76
77
78
79
80
81
82
83
<form action="{url}pushloghtml">
<div class="search">
<select class="querytype">
<option value="date">Date</option>
<option value="changeset">Changeset</option>
<option value="pushid">pushID</option>
</select>&nbsp;&nbsp;&nbsp;
From:
<input class="from" type="text" name="startdate"/>
To:
<input class="to" type="text" name="enddate"/>
<input class="submitquery" type="submit" value="Search"/>
</div>
</form>

Remembering the previously executed query

Now, this was a bit tricky. I experimented with 2 or 3 methods. There is the obvious method where I just read in whatever is entered and match it against a regex to see what type of query was executed. I decided not to take that approach. Then, I looked at using jquery to read the selected item in the drop down list when the search button gets clicked. That didn’t work for me. I ended up looking at the query string to find out what query got executed.

So in the above code (line 38) I just retrieve the query string and do an indexOf to find the query type. It ended up being pretty simple.

Don’t remove the values entered by the user

To improve usability, ted recommended that I shouldn’t reset the text box value when the drop down selection changes. First of all I decided to remove the default date that you currently find in the text boxes. This is because if I make a changeset query via the new UI, after the page loads the default date values re-appear in the text boxes since they are hard coded.

Now when the change event occurs I don’t set the value and so if the user decides to change the query type the values he entered will not change.

The 3rd pushlog query

There is another pushlog query that takes in a startID and an endID. I’ve added this new query option to the drop down menu as well.

Unfortunately for this patch showing screenshots won’t help at all since you have to try it out for yourself to see whether the implementation works correctly or not. I’ll be putting up the patch soon so whoever is interested can get it from the bug page and try it out for themselves.

,

No Comments

v0.9 Release - Updating the Files Touched Patch

So, as I had mentioned in my goals blog post, I would be updating my files touched patch to work with the new code now found in the repo. First of all lets have a look at my old code:

248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
def changelist(limit=0, **map):
  allentries = []
  lastid = None
  ch = None
  l = []
  for id, user, date, node in entries:
      filesTouched = ''
      ctx = web.repo.changectx(node)
      if len(ctx.files()) > 1:
        for f in ctx.files():
          filesTouched += f + '<br/>'
      else:
        for f in ctx.files():
          filesTouched += f
      if id != lastid:
          lastid = id
          l.append({"parity": parity.next(),
                    "user": user,
                    "date": localdate(date),
                    'numchanges': 0,
                    "changes": []})
          ch = l[-1]['changes']
      ctx = web.repo.changectx(node)
      n = ctx.node()
      ch.append({"author": ctx.user(),
                 "desc": ctx.description(),
                 "files": web.listfilediffs(tmpl, ctx.files(), n),
                 "rev": ctx.rev(),
                 "node": hex(n),
                 "tags": nodetagsdict(web.repo, n),
                 "branches": nodebranchdict(web.repo, ctx),
                 "inbranch": nodeinbranch(web.repo, ctx),
                 "parity": l[-1]["parity"],
                 "filesTouched": filesTouched
                 })
      l[-1]['numchanges'] += 1
 
  if limit > 0:
      l = l[:limit]
 
  for e in l:
      yield e
pushlogchange = '<td class="age"><a href="{url}rev/#node|short#{sessionvars%urlparameter}">#node|short#</a></td><td><strong>#author|person# &mdash; #desc|strip|escape|buglink#</strong><br/><span style="font-size: x-small; color: #996633; font-weight: bold">#filesTouched#</span> <span class="logtags">{inbranch%inbranchtag}{branches%branchtag}{tags%tagtag}</span></td></tr><tr class="parity#parity#">'

pushlog-feed.py has changed quite a bit since I submitted this patch a few months back. Thus, I’ll have to change my code a bit. Even the map file has changed but my code itself (for the map file) won’t be changing much. I’ll just be placing it in a different area. Also, as you can see above I have the CSS within the span tag. That has to be moved to the a stylesheet.

Lets look at my solution:

365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
def changelist(limit=0, **map):
  # useless fallback
  listfilediffs = lambda a,b,c: []
  if hasattr(webutil, 'listfilediffs'):
      listfilediffs = lambda a,b,c: webutil.listfilediffs(a,b,c, len(b))
  elif hasattr(web, 'listfilediffs'):
      listfilediffs = web.listfilediffs
 
  allentries = []
  lastid = None
  ch = None
  l = []
  mergehidden = ""
  filesTouched = ""
  p = 0
  currentpush = None
  for id, user, date, node in query.entries:
      ctx = web.repo.changectx(node)
      n = ctx.node()
      entry = {"author": ctx.user(),
               "desc": ctx.description(),
               "files": listfilediffs(tmpl, ctx.files(), n),
               "rev": ctx.rev(),
               "node": hex(n),
               "tags": nodetagsdict(web.repo, n),
               "branches": nodebranchdict(web.repo, ctx),
               "inbranch": nodeinbranch(web.repo, ctx),
               "hidden": "",
               "push": [],
               "mergerollup": [],
               "filesTouched": filesTouched,
               "id": id
               }
      if id != lastid:
          lastid = id
          p = parity.next()
          entry["push"] = [{"user": user,
                            "date": localdate(date)}]
          if len([c for c in ctx.parents() if c.node() != nullid]) > 1:
              mergehidden = "hidden"
              entry["mergerollup"] = [{"count": 0}]
          else:
              mergehidden = ""
          currentpush = entry
 
 
 
      else:
          entry["hidden"] = mergehidden
          if mergehidden:
              currentpush["mergerollup"][0]["count"] += 1
      entry["parity"] = p
 
      for f in ctx.files():
        entry["filesTouched"] += '<br/>' + f
 
      l.append(entry)
 
  if limit > 0:
      l = l[:limit]
 
  for e in l:
      yield e
pushlogentry = '<tr class="parity#parity# #hidden# id#id#"><td>#push%pushinfo#</td><td class="age"><a href="{url}rev/#node|short#{sessionvars%urlparameter}">#node|short#</a></td><td><strong>#author|person# &mdash; #desc|strip|escape|buglink#</strong><span class="filetouch">{filesTouched}</span> <span class="logtags">{inbranch%inbranchtag}{branches%branchtag}{tags%tagtag}</span>#mergerollup%mergehidden#</td></tr>\n'
span.filetouch {
  font-family: sans-serif; 
  color: #996633; 
}

I have reduced the server side code a little but I’ve managed to retain the same functionality, which is always great. I moved the declaration of the filesTouched variable to the top where the rest of the variable declarations occur.

So, the entry dictionary holds the filesTouched key/value. I set the value in my for loop at line 415. In my previous code I had an if/else statement, which I have now removed. This is because before I had a static line break in the map file right before the files are displayed. I removed that and just decided to add a line break before each file is displayed (line 416). Now I don’t have to worry about whether there is only one file touched or more than one and add a line break accordingly (which is what the old if/else statement was for).

Also, as you can see the CSS now cleanly resides in the style-gitweb.css stylesheet. I still don’t know about the text color though. Does it match the color scheme of the gitweb_mozilla template? Not really but I couldn’t find any other color that was both readable and matched the theme. I guess I could have left the text black but I wanted to differentiate it somehow. I guess this is the difference between a programmer and a designer eh?

In the future (maybe my next release) I’ll look to add expand/collapse functionality for this bug since many times just one push can touch a large amount of files. For now, I hope this gets reviewed and approved soon so that people can start reaping its benefits.

,

No Comments

v0.9 Release Goals

The end of the semester is approaching rapidly (only 2 weeks left) and so is my time here at Seneca. I can’t believe 4 years have gone by so fast. No time to think about my time after graduation though. I’m in engulfed in work right now, a typical situation this late in the semester. Anyway, it’s time for yet another release.

This time I’m not going to touch my major bug. Instead, I’ll be making changes to three other bugs this time around. I’ll be revisting one of the bugs that I fixed last semester (files touched). It had been approved for a long time now but the patch never got applied to the repo and it seems to have bitrotted now. The next bug I will be tackling is the changesetUI one for which I need to make some changes. Last but not the least, I’ll will take on a new bug regarding line breaks for long messages. The following are the goals for this release:

  • Files touched - Update the patch to make it work with the new code in hgpoller and hg_templates. Also move the all the css to a stylesheet.
  • Changeset UI - ted reviewed the patch that I submitted for this bug and he doesn’t want me to set the value when the drop down changes. This would mean that whatever the user has already entered would be overwritten. I guess it makes sense, since you want to avoid that from a usability standpoint. Also I will look to re-write the code to take advantage of jquery which has been added to the repo now. Furthermore, there is another query for the pushlog that takes in two pushids. I will be adding that to the drop down list as well.
  • Line breaks turned into spaces - When a long message is displayed in the pushlog the linebreaks are not registered. My goal is to only show the first line and then show an ellipsis link that the user can click to show/hide the rest of the message that has the line breaks.

Fun stuff! Time to get to work!

, , ,

No Comments