Why is diff producing different differences when the files are given in the opposite order - diff

Please check the following two files
1. www.cse.iitb.ac.in/~ashu/opt1
2. www.cse.iitb.ac.in/~ashu/opt2
The output of diff -bB opt1 opt2 is empty, while that of diff -bB opt2 opt1 is non empty, and can be found at:
3. www.cse.iitb.ac.in/~ashu/diff
Why is this happening?

Related

Get last commit for every file of a file list in Mercurial

I have an hg repository and I would like to know the last commit date of every file in sources/php/dracca/endpoint/wiki/**/Wiki*.php
So far, I have this one liner:
find sources/php/dracca/endpoint/wiki/ -name "Wiki*.php" -exec hg log --limit 1 --template "{date|shortdate}" {} \; -exec echo {} \;
But this seems utterly slow as (I suppose) find makes 1 hg call per file, leading to 15seconds of computation for the (say) ~40 files I have in there...
Is there a faster way?
The output of this command looks like:
2019-09-20 sources/php/dracca/endpoint/wiki/characters/colmarr/WikiCharactersColmarrEndpoint.php
2019-09-20 sources/php/dracca/endpoint/wiki/characters/dracquints/allgroup/WikiCharactersDracquintsAllgroupEndpoint.php
...
It might be changed a bit if needed (I won't mind having, say, 1 date and then the list of files changed for that date, or whatever like this)
Even with find+exec you can have shorter (by one last exec) chain with modified template {date|shortdate}\n
You can use (accepted) perl-ism from this question or ask anybody to update mentioned lof extension to current Mercurial (code from 2012 will not work now)
Alternatives (dirty ugly hacks)
In any case, you can|have to call hg only once and perform some post-processing of results.
Before these trick, read hg help filesets and get one common fileset for your files (I suppose, it can be just set:sources/php/dracca/endpoint/wiki/**/Wiki*.php but TBT!)
After it, you can:
Perform hg log like this
hg log setup.* --template "{files % '{file} {rev} {date|shortdate}\n'}"
(I used simple pattern for test, you have to have own fileset)
get output in such form
setup.py 1163 2018-11-07
README.md 1162 2018-11-07
setup.py 1162 2018-11-07
hggit/git_handler.py 1124 2018-05-01
setup.py 1124 2018-05-01
setup.cfg 1118 2017-11-27
setup.py 1117 2017-11-27
hggit/git2hg.py 1111 2017-11-27
hggit/overlay.py 1111 2017-11-27
setup.py 1111 2017-11-27
…
(there are some unwanted unexpected files, because I out all files in revision, which affect file in interest, without filter). You have to grep only needed files, sort by cols 1+2 and use date of latest revision of each file
Use hg grep. For the above test-pattern
hg grep "." -I setup.* --files-with-matches -d -q
(find any changes, output only filename+revision, short date)
you'll get something like
setup.py:1163:2018-11-07
setup.cfg:1118:2017-11-27
and 3-rd column will be your needed last modification date of file

How do you find the changesets between two tags in mercurial?

If I have two tags named 2.0 and 2.1, how do I find the changeset messages between the two? I'm trying to find to a way to use HG make release notes and list the different messages associated with the commits.
Example Changeset:
changeset: 263:5a4b3c2d1e
user: User Name <user.name#gmail.com>
date: Tue Nov 27 14:22:54 2018 -0500
summary: Added tag 2.0.1 for changeset 9876fghij
Desired Output:
Added tag 2.1 for changeset 67890pqrst
Change Info...
Added tag 2.0.1 for changeset 9876fghij
Change Info...
Added tag 2.0 for changeset klmno12345
Preface
"Any challenge has a simple, easy-to-understand wrong decision". And Boris's answer is a nicest illustration for this rule: "::" topo-range will produce good results only in case of pure single-branch development (which is, in common, The Bad Idea (tm) anyway)
Face
Good solution must correctly handle complex DAGs and answer on question "New changesets included in NEW, missing in OLD (regardless of the nature of occurrence)"
For me it's "only()" functions in revsets with both parameters
"only(set, [set])"
Changesets that are ancestors of the first set that are not ancestors
of any other head in the repo. If a second set is specified, the
result is ancestors of the first set that are not ancestors of the
second set (i.e. ::set1 - ::set2).
hg log -r "only(2.1,2.0)"
maybe for better presentation powered by predefined style "changelog"
hg log -r "only(2.1,2.0)" -s changelog
or custom style|template
You'll want to use a revset to select all changesets between two tags, for example: 2.0::2.1 will likely do the trick. You can validate the selected changesets by running: hg log -G -r '2.0::2.1'. (See hg help revset for more information about revsets).
Once you have the right selected changesets, you can now apply a template to retrieve only the needed information. For example if you only want the first line of changeset description, you can do hg log -r '2.0::2.1' -T '{desc}\n' for the whole description or hg log -r '2.0::2.1' -T '{desc|firstline}\n' only for the first line of each changeset description.
If you want to add even more information, hg help template is your friend.

In Mercurial, move old file to location, move new files into old file location with same names

This should be simple, but something isn't quite right. Here is my scenario and then I'll give a brief overview of the commands I'm using. It helps to know that we have 3 specific dev areas, Live, Staging, and of course our own local dev areas.
I developed a new "beta" area of my site which has gone live and had appropriate testing. Now I'm ready to move it from a beta directory, to where it really should be and move out the old. When I do it locally, it seems fine, but when I try to merge my local branch into the staging branch, it doesn't seem to map the files correctly, and gives me a bunch of those use (c)hanged version, (d)elete, or leave (u)nresolved? prompts. The problem comes when my old directory has files that are named the same as the beta directory (like index.php for instance). Here's a quick example of what I mean:
currentDir/index.php
currentDir/update.php
currentDir/another_file.php
currentDir-beta/index.php
currentDir-beta/update.php
currentDir-beta/a_new_file.php
currentDir-beta/another_new_file.php
This is my process.
# creates a new branch from the live branch
hg branch new-branch-name
# move the current directory somewhere else
hg mv currentDir/* currentDir-old/
# commit...
hg com -m "moved current to -old"
# everything is fine up to this point
# move the beta directory to where the old one was
hg mv currentDir-beta/* currentDir/
# when I run hg st, it only shows that files are being removed from the -beta directory and added to the new/old directory
# commit
hg com -m "moved -beta to currentDir"
# when this commits is when the problems start happening.
# At this point when I run this next command, it shows that
# currentDir/index.php and other common files are now "modified" instead of "added"
hg st --rev "max(ancestors('new-branch-name') and branch(live)):'new-branch-name'"
# then try to merge to staging
hg up staging
hg merge new-branch-name
# errors happen with "common" file names like index.php. It treats them as though they were only modified instead of added.
Even if I ignored the above "modified" quirk, when I go to merge this new branch into the staging branch with other changes programmers have done, it complains that "local has this which remote deleted". I really wouldn't care with most of this as I could just throw this live and then any new branches would have this change. The thing I do care about is that any work done in the currentDir-beta folder on those "common" files from other programmers will no longer map to the new location. I can copy/paste the code and commit it, but it basically means that those branches are hosed as it pertains to keeping the changes other programmers did on those common files. To give you an example of what I mean, when I merge and type hg st it might look something like this.
M currentDir/index.php
M currentDir/update.php
M currentDir/a_new_file.php # why is this M? It should be A right?
M currentDir/another_new_file.php # why is this M? It should be A right?
M currentDir-old/another_file.php # why is this M? It should be A right?
R currentDir/another_file.php
R currentDir-beta/index.php
R currentDir-beta/update.php
R currentDir-beta/a_new_file.php
R currentDir-beta/another_new_file.php
Any suggestions on how to get around this? My goal is to make it so existing code changes that took place in currentDir-beta are "forwarded" to currentDir/ in the staging environment. All the other "not common" file changes are mapped, just not these common files.
UPDATE
Forgot to mention, I'm using Mercurial 3.9 on macOS Sierra.
I don't know
Your version of Mercurial
OS
but on my Win-box with Mercurial-3.9.1 my impressions (and results) differ
Clean initial state (folders shortened due to lazyness)
>hg st -A
C Current-beta\a_new_file.php
C Current-beta\another_new_file.php
C Current-beta\index.php
C Current-beta\update.php
C Current\another_file.php
C Current\index.php
C Current\update.php
First rename
>hg mv Current Current-Backup
moving Current\another_file.php to Current-Backup\another_file.php
moving Current\index.php to Current-Backup\index.php
moving Current\update.php to Current-Backup\update.php
...commit details skipped...
Second rename
>hg mv Current-beta Current
moving Current-beta\a_new_file.php to Current\a_new_file.php
moving Current-beta\another_new_file.php to Current\another_new_file.php
moving Current-beta\index.php to Current\index.php
moving Current-beta\update.php to Current\update.php
and working directory after it (as expected)
>hg st
A Current\a_new_file.php
A Current\another_new_file.php
A Current\index.php
A Current\update.php
R Current-beta\a_new_file.php
R Current-beta\another_new_file.php
R Current-beta\index.php
R Current-beta\update.php
...commit details skipped...
If you want to see how it was recorded by Mercurial: I used such slightly puzzling at first glance log for better interpreting of output
hg log -T "{rev}:{node|short}\n{if(file_adds,'\tAdded: {join(file_adds,', ')}\n')}{if(file_copies,'\tCopied: {join(file_copies,', ')}\n')}{if(file_dels,'\tDeleted: {join(file_dels,', ')}\n')}{if(file_mods,'\tModified: {join(file_mods,', ')}\n')}\n"
and here it's result
2:98955fcb7e71
Added: Current/a_new_file.php, Current/another_new_file.php, Current/index.php, Current/update.php
Copied: Current/a_new_file.php (Current-beta/a_new_file.php), Current/another_new_file.php (Current-beta/another_new_file.php), Current/index.php (Current-beta/index.php), Current/update.php (Current-beta/update.php)
Deleted: Current-beta/a_new_file.php, Current-beta/another_new_file.php, Current-beta/index.php, Current-beta/update.php
1:61068c6ba8a7
Added: Current-Backup/another_file.php, Current-Backup/index.php, Current-Backup/update.php
Copied: Current-Backup/another_file.php (Current/another_file.php), Current-Backup/index.php (Current/index.php), Current-Backup/update.php (Current/update.php)
Deleted: Current/another_file.php, Current/index.php, Current/update.php
0:454486bc43e5
Added: Current-beta/a_new_file.php, Current-beta/another_new_file.php, Current-beta/index.php, Current-beta/update.php, Current/another_file.php, Current/index.php, Current/update.php
As you can see - no edits ("Modified") at all (and here log /per changeset/ is more correct than aggregated status)
PS: I couldn't see on the fly purpose of your revset in hg st and necessity of branching+merging
PPS: OK, I saw
>hg st --rev "0:"
M Current\index.php
M Current\update.php
A Current-Backup\another_file.php
A Current-Backup\index.php
A Current-Backup\update.php
A Current\a_new_file.php
A Current\another_new_file.php
R Current-beta\a_new_file.php
R Current-beta\another_new_file.php
R Current-beta\index.php
R Current-beta\update.php
R Current\another_file.php
Aggregated results in considering only the boundary conditions is (correctly, technically speaking) modified files for files 1) in the same location 2) with the same name 3) and with changed content

Mercurial fails to merge via command line

My mercurial installation refuses to merge via command line. Here's the output after I turn on verbose and debug.
C:\src\StackOverflow>hg resolve --all --verbose --debug
couldn't find merge tool codecompare_diff
couldn't find merge tool codecompare_merge
couldn't find merge tool bcompare
couldn't find merge tool beyondcompare3
couldn't find merge tool beyondcompare3-noauto
couldn't find merge tool rekisa
couldn't find merge tool UltraCompare
couldn't find merge tool araxis
couldn't find merge tool meld
couldn't find merge tool diffuse
picked tool 'kdiff3' for StackOverflow/StackOverflow.csproj (binary False symlink False)
merging StackOverflow/StackOverflow.csproj
my StackOverflow/StackOverflow.csproj#4f4faeac0fea+ other StackOverflow/StackOverflow.csproj#ae29e8c6bb88 ancestor StackOverflow/StackOverflow.csproj#399376fedfc5
The system cannot find the path specified.
merging StackOverflow/StackOverflow.csproj failed!
Note: the merge was actually successful (kdiff3 pops up, I merge and save), but mercurial is confused.
How do I determine which path cannot be found by Mercurial?
I've tried updating to the latest version (2.8) and looking at my mercurial.ini for any suspicious files. I've also used a different merge tool, p4merge, to the same exact effect.
Hmm... Actually.
It may be stupid "solution", but you may look into the filemerge.py file that should come with mercurial.
This file defines how mercurial is doing merge (calling external merge-tools, processing result, etc).
Here you see the following lines inside the filemerge function:
ui.debug("picked tool '%s' for %s (binary %s symlink %s)\n" %
(tool, fd, binary, symlink))
[...]
ui.status(_("merging %s\n") % fd)
ui.debug("my %s other %s ancestor %s\n" % (fcd, fco, fca))
They are giving correspondent messages in your output:
picked tool 'kdiff3' for StackOverflow/StackOverflow.csproj (binary False symlink False)
merging StackOverflow/StackOverflow.csproj
my StackOverflow/StackOverflow.csproj#4f4faeac0fea+ other StackOverflow/StackOverflow.csproj#ae29e8c6bb88 ancestor StackOverflow/StackOverflow.csproj#399376fedfc5
Then _xmerge function is called from filemerge function with the following lines:
needcheck, r = func(repo, mynode, orig, fcd, fco, fca, toolconf,
(a, b, c, back))
And then the ui.warn(onfailure % fd) is reached either at line 334 or at line 368 (I don't know), which gives your last error message:
merging StackOverflow/StackOverflow.csproj failed!
Somewhere between ui.debug("my %s other %s ancestor %s\n" % (fcd, fco, fca)) and ui.warn(onfailure % fd) there is a reason why ui.warn(onfailure % fd) is actually reached (maybe in _xmerge). You can try to discover it by inserting various debug output in various places of filemerge.py file, and retrying merge. That's all I can currently recommend (as I can't reproduce your errors and context on my machine).
P.S.: As santiagopim suggests, you may prefer to copy WC to the clean PC with clean mercurial installation and retry there. As the errors are most probably caused by some misconfiguration. However, if you prefer to try to resolve problem in-place...

Find deleted files in Mercurial repository history, quickly?

You can use hg grep, but it searches the contents of all files.
What if I just want to search the file names of deleted files to recover one?
I tried hg grep -I <file-name-pattern> <pattern> but this seems to return no results.
using templates is simple:
$ hg log --template "{rev}: {file_dels}\n"
Update for Mercurial 1.6
You can use revsets for this too:
hg log -r "removes('**')"
(Edit: Note the double * - a single one detects removals from the root of the repository only.)
Edit: As Mathieu Longtin suggests, this can be combined with the template from dfa's answer to show you which files each listed revision removes:
hg log -r "removes('**')" --template "{rev}: {file_dels}\n"
That has the virtue (for machine-readability) of listing one revision per line, but you can make the output prettier for humans by using % to format each item in the list of deletions:
hg log -r "removes('**')" --template "{rev}:\n{file_dels % '{file}\n'}\n"
If you are using TortoiseHg workbench, a convenient way is to use the revision filter. Just hit ctrl+s, and then type
removes("**/FileYouWantToFind.txt")
**/ indicates that you want to search recursively in your repository.
You can use * wildcard in the filename too. You can combine this query with other revision sets using and, or operators.
There is also this Advanced Query Editor:
I have taken other answers and improved it.
Added "--no-merges". On large project with dev teams, there will lots of merges. --no-merger will filter out the log noise.
Change removes("**") to sort(removes("**"), -rev). For a large project with over 100K changesets, this will get to the latest files removed a lot faster. This reverses the order from starting at rev 0 to start at tip instead.
Added {author} and {desc} to ouput. This will give context as to why the files was removed by displaying the log comment and who did it.
So for my use case, it was hg log --template "File(s) deleted in rev {rev}: {author} \n {desc}\n {file_dels % '\n {file}'}\n\n" -r 'sort(removes("**"), -rev)' --no-merges
Sample output:
File(s) deleted in rev 52363: Ansariel
STORM-2141: Fix various inventory floater related issues:
* Opening new inventory via Control-Shift-I shortcut uses legacy and potentinally dangerous code path
* Closing new inventory windows don't release memory
* During shutdown legacy and inoperable code for inventory window cleanup is called
* Remove old and unused inventory legacy code
indra/newview/llfloaterinventory.cpp
indra/newview/llfloaterinventory.h
File(s) deleted in rev 51951: Ansariel
Remove readme.md file - again...
README.md
File(s) deleted in rev 51856: Brad Payne (Vir Linden) <vir#lindenlab.com>
SL-276 WIP - removed avatar_skeleton_spine_joints.xml
indra/newview/character/avatar_skeleton_spine_joints.xml
File(s) deleted in rev 51821: Brad Payne (Vir Linden) <vir#lindenlab.com>
SL-276 WIP - removed avatar_XXX_orig.xml files.
indra/newview/character/avatar_lad_orig.xml
indra/newview/character/avatar_skeleton_orig.xml
Search for a specific file you deleted efficiently, and format the result nicely:
hg log --template "File(s) deleted in rev {rev}: {file_dels % '\n {file}'}\n\n" -r 'removes("**/FileYouWantToFind.txt")'
Sample output:
File(s) deleted in rev 33336:
class/WebEngineX/Database/RawSql.php
File(s) deleted in rev 34468:
class/PdoPlus/AccessDeniedException.php
class/PdoPlus/BulkInsert.php
class/PdoPlus/BulkInsertInfo.php
class/PdoPlus/CannotAddForeignKeyException.php
class/PdoPlus/DuplicateEntryException.php
class/PdoPlus/Escaper.php
class/PdoPlus/MsPdo.php
class/PdoPlus/MyPdo.php
class/PdoPlus/MyPdoException.php
class/PdoPlus/NoSuchTableException.php
class/PdoPlus/PdoPlus.php
class/PdoPlus/PdoPlusException.php
class/PdoPlus/PdoPlusStatement.php
class/PdoPlus/RawSql.php
from project root
hg status . | grep "\!" >> /tmp/filesmissinginrepo.txt