have number of modified and unknown mercurial files on prompt - regex

I'm using the hg prompt extension to have a nice prompt while working with hg.
Right now my prompt looks like this:
~/my/current/path [hg default !]
the '!' part in the prompt I get via the {status} keyword of the hg prompt showing me that are modified files. It shows a '?' for unknown files
But I want something similar to posh-hg where it also shows the number of modified or unknown files.
I know I can get this information with hg summary but my sed fu is failing me on getting the regex correct to get the totals.
an example of the output of the hg summary command:
parent: 0:16ed527e220f tip
parent commit message
branch: default
commit: 5 modified, 2 unknown
update: (current)
doing a hg summary | grep 'commit' I get back the correct line:
$ hg summary | grep 'commit'
commit: 5 modified, 2 unknown
given the output above, how can I get the number of modified and unknown files so that I can make my prompt look like this:
[hg default 5! 2?]

This works:
hg sum | sed -ne '/^commit:/{s/^commit: //;s/ modified/\!/;s/ unknown/?/;s/,//g;p}'
... although there might be a more elegant way to do it.
You can probably figure out the added, deleted etc part by yourself.

Related

search both history log and files on git, with termux and regexp

tried every answer from similar questions:
How to grep Git commit diffs or contents for a certain word?
Search all of Git history for a string?
How to grep (search) committed code in the Git history
none worked!
would it even be possible to search using anything other than git itself?
repository tested: http://cregox.net
scenario
picture hundreds of markdown files, a dozens of which will have something like this:
---
title: lorem ipsum
description: foo, or not foo, it's not even a question
bar: false
(in practice, instead of foo it was checklist and instead of bar i wanted published)
expected
ag "foo[\s\S]*bar:\ "
will search all files with 1 foo that happens before the first bar: if they both exist.
all i needed was that, applied to git history.
that's it.
but...
reality
git log -G "foo[\s\S]*bar:\ "
instead of silversearcher-ag doesn't even work because of \s.
i've tried many variations of regexp, couldn't find any single one that would work!
so that's something that i'll want to fix at some point, but meanwhile i also tried other alternatives...
git log -p -S foo
should bring something similar to rg foo, but doesn't come even close to be readable and it's way too verbose.
git log --name-status --oneline -S foo
this was the closest i could get to the expected results... but it's still too cumbersome.
i give up digging for now.
With git log regex following should work for you to match across the lines:
git log --name-status --oneline -G 'foo(\S|\s)+bar:\s'

Mass rename in shell script

I have a bunch of files which are of this format:
blabla.log.YYYY.MM.DD
Where YYYY.MM.DD is something like (2016.01.18)
I have quite a few folders with about 1000 files in each, so I wanted to have a simple script to rename them. I want to rename them to
blabla.log
So basically, I'm just stripping the date at the end. Here is what I have:
for f in [a-zA-Z]*.log.[0-9][0-9][0-9][0-9].[0-9][0-9].[0-9][0-9]; do
mv -v $f ${f#[0-9][0-9][0-9][0-9].[0-9][0-9].[0-9][0-9]};
done
This script outputs this:
mv: `blabla.log.2016.01.18' and `blabla.log.2016.01.18' are the same file
For more information:
I'm on windows, but I run this script in gitbash
For some reason, my gitbash doesn't recognize the "rename" command
Some regex patterns (like [0-9]{4} don't seem to work)
I'm really at a lost. Thanks.
EDIT: I need to rename every single file that has a date at the end and that is of the from: *.log.2016.01.18. They all need to keep their original names. All that should change is the removal of the date.
You have to use % instead of #: you want to remove from the end, not the start of your string.
Also, you're missing a . in what has to be removed, you don't want to end up with blabla.log..
Quoting the variable names prevents surprises when file names contain special characters.
Together:
mv -v "$f" "${f%.[0-9][0-9][0-9][0-9].[0-9][0-9].[0-9][0-9]}"

Get all changed files in a changest

I want to get all the changed file in a changeset but without having the letter that specify the change type.
I know this command
hg status --change changeset
However, this return result like,
A /path/to/file
M /path/to/file
I want the result to be
/path/to/file
without "A" or "M". I tried to do it with regular expression and it used to work but I don't know it didn't work in one scenario.
The regular expression,
/(?<=[MA]\s).+/
This the scenario that did not work
arwa/Documents/Projects/firefox/M db << notice M here.
Any thought?
You should add ^ (start of line) to your regex:
/(?<=^[MA]\s).+/
If you don't do that, (?<=[MA]\s) will lookabehind the M part and .+ will catch db.
As of Mercurial 3.5, you can use templates (still an experimental feature, you can see it with hg help status -v). Namely:
hg status --change <rev> --template '{path}\n'
Why not use log with template?
hg log -r CSET -T "{files % '{file}\n'}"
will produce clean output
lang/UTF-8/serendipity_lang_ru.inc.php
plugins/serendipity_event_bbcode/UTF-8/lang_ru.inc.php
plugins/serendipity_event_emoticate/UTF-8/lang_ru.inc.php
plugins/serendipity_event_karma/UTF-8/lang_ru.inc.php
plugins/serendipity_event_s9ymarkup/UTF-8/lang_ru.inc.php
plugins/serendipity_plugin_shoutbox/UTF-8/lang_ru.inc.php
contrary to templated status
'lang\UTF-8\serendipity_lang_ru.inc.php
''plugins\serendipity_event_bbcode\UTF-8\lang_ru.inc.php
''plugins\serendipity_event_emoticate\UTF-8\lang_ru.inc.php
''plugins\serendipity_event_karma\UTF-8\lang_ru.inc.php
''plugins\serendipity_event_s9ymarkup\UTF-8\lang_ru.inc.php
''plugins\serendipity_plugin_shoutbox\UTF-8\lang_ru.inc.php
'

How to substitute words in Git history & properly debug related problems?

I'm trying to remove sensitive data like passwords from my Git history. Instead of deleting whole files I just want to substitute the passwords with removedSensitiveInfo. This is what I came up with after browsing through numerous StackOverflow topics and other sites.
git filter-branch --tree-filter "find . -type f -exec sed -Ei '' -e 's/(aSecretPassword1|aSecretPassword2|aSecretPassword3)/removedSensitiveInfo/g' {} \;"
When I run this command it seems to be rewriting the history (it shows the commits it's rewriting and takes a few minutes). However, when I check to see if all sensitive data has indeed been removed it turns out it's still there.
For reference this is how I do the check
git grep aSecretPassword1 $(git rev-list --all)
Which shows me all the hundreds of commits that match the search query. Nothing has been substituted.
Any idea what's going on here?
I double checked the regular expression I'm using which seems to be correct. I'm not sure what else to check for or how to properly debug this as my Git knowledge quite rudimentary. For example I don't know how to test whether 1) my regular expression isn't matching anything, 2) sed isn't being run on all files, 3) the file changes are not being saved, or 4) something else.
Any help is very much appreciated.
P.S.
I'm aware of several StackOverflow threads about this topic. However, I couldn't find one that is about substituting words (rather than deleting files) in all (ASCII) files (rather than specifying a specific file or file type). Not sure whether that should make a difference, but all suggested solutions haven't worked for me.
git-filter-branch is a powerful but difficult to use tool - there are several obscure things you need to know to use it correctly for your task, and each one is a possible cause for the problems you're seeing. So rather than immediately trying to debug them, let's take a step back and look at the original problem:
Substitute given strings (ie passwords) within all text files (without specifying a specific file/file-type)
Ensure that the updated Git history does not contain the old password text
Do the above as simply as possible
There is a tailor-made solution to this problem:
Use The BFG... not git-filter-branch
The BFG Repo-Cleaner is a simpler alternative to git-filter-branch specifically designed for removing passwords and other unwanted data from Git repository history.
Ways in which the BFG helps you in this situation:
The BFG is 10-720x faster
It automatically runs on all tags and references, unlike git-filter-branch - which only does that if you add the extraordinary --tag-name-filter cat -- --all command-line option (Note that the example command you gave in the Question DOES NOT have this, a possible cause of your problems)
The BFG doesn't generate any refs/original/ refs - so no need for you to perform an extra step to remove them
You can express you passwords as simple literal strings, without having to worry about getting regex-escaping right. The BFG can handle regex too, if you really need it.
Using the BFG
Carefully follow the usage steps - the core bit is just this command:
$ java -jar bfg.jar --replace-text replacements.txt my-repo.git
The replacements.txt file should contain all the substitutions you want to do, in a format like this (one entry per line - note the comments shouldn't be included):
PASSWORD1 # Replace literal string 'PASSWORD1' with '***REMOVED***' (default)
PASSWORD2==>examplePass # replace with 'examplePass' instead
PASSWORD3==> # replace with the empty string
regex:password=\w+==>password= # Replace, using a regex
Your entire repository history will be scanned, and all text files (under 1MB in size) will have the substitutions performed: any matching string (that isn't in your latest commit) will be replaced.
Full disclosure: I'm the author of the BFG Repo-Cleaner.
Looks OK. Remember that filter-branch retains the original commits under refs/original/, e.g.:
$ git commit -m 'add secret password, oops!'
[master edaf467] add secret password, oops!
1 file changed, 4 insertions(+)
create mode 100644 secret
$ git filter-branch --tree-filter "find . -type f -exec sed -Ei '' -e 's/(aSecretPassword1|aSecretPassword2|aSecretPassword3)/removedSensitiveInfo/g' {} \;"
Rewrite edaf467960ade97ea03162ec89f11cae7c256e3d (2/2)
Ref 'refs/heads/master' was rewritten
Then:
$ git grep aSecretPassword `git rev-list --all`
edaf467960ade97ea03162ec89f11cae7c256e3d:secret:aSecretPassword2
but:
$ git lola
* e530e69 (HEAD, master) add secret password, oops!
| * edaf467 (refs/original/refs/heads/master) add secret password, oops!
|/
* 7624023 Initial
(git lola is my alias for git log --graph --oneline --decorate --all). Yes, it's in there, but under the refs/original name space. Clear that out:
$ rm -rf .git/refs/original
$ git reflog expire --expire=now --all
$ git gc
Counting objects: 6, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (4/4), done.
Writing objects: 100% (6/6), done.
Total 6 (delta 0), reused 0 (delta 0)
and then:
$ git grep aSecretPassword `git rev-list --all`
$
(as always, run filter-branch on a copy of the repo Just In Case; and then removing original refs, expiring the reflog "now", and gc'ing, means stuff is Really Gone).

Detecting errors of a command that print nothing if the command was successful using Perl and Expect

I am trying to automate the configuration of a server using perl and the expect module. I have been using the expect module three days but now I have encountered a problem that I can't solve.
My problem is when im executing a command that prints no output if it is successful but prints an error message if something went wrong. An example of such command is the cd command:
$ cd .
$
$ cd sadjksajdlaskd
sadjksajdlaskd: No such file or directory.
$
What I would like to do is to send the command to the server, and then perform an expect call to check if something other than the prompt sign was printed. Something like this:
$com->send("cd $dir");
$com->expect(2,
["^[^$#]*", sub {
my $self = shift;
my $error = $self->match();
die "ERROR: $error";
}],
"-re", "^[$#]"
);
The problem I have is that when I perform the expect call it will match against all previous text and not against text received after the send call, so it will always match and report an error. How do I make expect match only agains the text received after the send call? Is it possible to clear the buffer of the expect module or is it possible to achieve this kind of error detection some other way?
I also wonder how the expect module handles regular expressions. If I for example use "^[$#]\$" as the regular expression to match the prompt of the terminal, will the \$ part of the regular expression match end of line or an actual dollar sign? If i remove the \ perl complains.
Thanks in advance!
/Haso
EDIT: I have found a solution:
The solution was to use $com->clear_accum() which clears the accumelator. I have tried using it before but it seems like this function only works at random, or maybe I don't understand what clear_accum() is suppose to do.
EDIT: A final note about clear_accum():
The reason the clear_accum() function seems to work at random is because the text generated from the previous send is not read into the accumelator until an expect() call is made. So in order to truly clear all previous data is to first perform an expect() call and then clear the accumelator:
#To clear all previous data
$com->expect(0);
$com->clear_accum();
akarageo#Pal4op:~> cd banana
bash: cd: banana: No such file or directory
akarageo#Pal4op:~:( > echo $?
1
i.e. check the error code that CD returns, 0 means OK anything else is an error, No need to check the prompt , and btw, the CD command does not generate the prompt the shell does, so that must be part of your confusion also.
try $object->exitstatus() if it is of any help