Shorthand command to remove a dir, while retaining integrity of everything under it? - apache

I am working in a unix environment, and I am curious if there is a nifty/shorthand way to do the following.
remove the first of the foo directories.
(not: the first foo dir has nothing in it but the subsequent foo dir/* )
/directory1/foo/foo/bar/baz/
to:
/directory1/foo/bar/baz/
while keeping the integrity of everything under foo/bar/baz.
I am building a server and I inadvertently created an additional folder.
Of course, I can copy everything from foo/* into another folder, delete everything then grab it and put it back without the first foo. curious if there was a shorthand way of doing this.
Thanks

You could find the inode of foo directories, then unlink the first one, and link the second one in it's place, but I have yet to find a way to link inodes directly with the ln command.
Instead, you could do this:
ln /directory/foo/foo /directory/foonew && unlink /directory/foo/foo && unlink /directory/foo && mv /directory/foonew /directory/foo

mv /directory1/foo/foo/* /directory1/foo && rmdir /directory1/foo/foo

Related

Get directories count of IPFS

I installed the ipfs version 0.8.0 on WSL Ubuntu 18.04. Started ipfs using sudo ipfs daemon. Added 2 directories using the command sudo ipfs add -r /home/user/ipfstest, it results like this:
added QmfYH2KVxANPA3um1W5MYWA6zR4Awv8VscaWyhhQBVj65L ipfstest/abc.sh
added QmTXny9ZjuFPm4C4KbQSEYxvUp2MYbSCLppPQirW7ap4Go ipfstest
Likewise, I added one more directory having 2 files. Now, I need the total files and directories in my ipfs using go-ipfs-api. Following is my code:
package main
import (
"fmt"
"context"
"os"
"net/http"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promhttp"
"github.com/ipfs/go-ipfs-api"
)
var sh *shell.Shell
func main() {
sh := shell.NewShell("localhost:5001")
dir,err:=sh.FilesLs(context.TODO(),"")
if err != nil {
fmt.Fprintf(os.Stderr, "error: %s", err)
os.Exit(1)
}
fmt.Printf("Dir are: %d", dir)
pins,err:=sh.Pins()
if err != nil {
fmt.Fprintf(os.Stderr, "error: %s", err)
os.Exit(1)
}
fmt.Printf("Pins are: %d", len(pins))
dqfs_pincount.Add(float64(len(pins)))
prometheus.MustRegister(dqfs_pincount)
http.Handle("/metrics", promhttp.Handler())
http.ListenAndServe(":8090", nil)
}
If I run this code, I get the output as:
Dir are: [824634392256] Pins are: 18
Pinned files are incremented as I added files. But what is this output [824634392256]? And why only one?
I tried giving a path to the function dir,err:=sh.FilesLs(context.TODO(),"/.ipfs"). As I guess the files and dir's must be stored in ~/.ipfs. But this gives an error:
error: files/ls: file does not exist
How can I get all directories of ipfs? Where I am mistaken? what path should I prove as a parameter? Please help and guide.
There's a bit to unpack here.
Why are you using sudo?
IPFS is meant to be run as a regular user. Generally you don't want to run it as root, but you'd instead run the same commands, just without sudo:
ipfs daemon
ipfs add -r /home/user/ipfstest
...
Code doesn't compile
Let's begin with the code, and make sure that's working as intended before moving forward, first off your import:
"github.com/ipfs/go-ipfs-api"
Should read:
shell "github.com/ipfs/go-ipfs-api"
As otherwise the code won't compile, because of your usage of shell later in the code.
Why does dir produce the output it does?
Next, let's look at your usage of dir. You're storing *[]MfsLsEntry (MfsLsEntry), which is a slice of pointers. You're outputting that with string formatting %d, which will be a base10 integer (docs), so the "824634392256" is just the memory address of the MfsLsEntry object in the first index of the slice.
Why does sh.FilesLs(context.TODO(),"/.ipfs") fail?
Well FilesLs isn't querying your own regular filesystem that your OS runs on, but actually MFS. MFS is stored locally though, but using the add API doesn't automatically add something to your MFS. You can use FilesCp to add a CID to your MFS after you add it though.
How do I list my directories on IPFS?
This is a bit of a tricky question. The only data really retain on IPFS is either data pinned, or data referenced in the MFS. So above we already learned the FilesLs command lists the files/directories on your MFS. To list your recursive pins (directories), it's quite simple using the command line:
ipfs pin ls -t recursive
For the API though, you'll first want to call something like Shell.Pins(), filter out for the pins you want (maybe a quick scan through, pull out anything recursive), then query the CIDs using Shell.ObjectStat or whatever you prefer.
If working with the pins though, do remember that it won't feel quite like a regular mutable filesystem, because it isn't. It's much easier to navigate through CIDs added to MFS. So that's how I'd recommend you list your directories on IPFS.

Is there a way to move a file from one branch to another in ClearCase?

A user checked new files on the wrong branch. I would like to move them in the most efficient way there is a lot of them. My first thought is to remove the element from the branch and have the user recheck in the files on the proper branch. But I was hoping there was a way i could change the pointers?
/VOB/DIRECTORY/file##/main/1.00/1 to /VOB/DIRECTORY/file##/main/2.00/1
Whenever there are a lot of files to checkout and move, clearfsimport is a viable option.
Simply set a view to the destination branch, and import the files found in the source (and wrong) view.
See "How can I use ClearCase to “add to source control …” recursively?"
That will checkout, add, modify or remove files in the destination view in order to mirror the ones from the source (here the source is a ClearCase view, but it could actually be any folder, ClearCase view or not, where the files are).
That will be enough to "recheck in the files on the proper branch", but that won't remove the versions from the wrong branch though, and I would advice against using cleartool rmver (even though I used that here).
Perhaps a subtractive merge is better.
If you know where they are, and where you want them, you could:
1) Merge the directory and files over.
2) Use cleartool ln in a view in the destination branch to link in the files, and then merge the files individually.
If you use clearfsimport, and don't purge the added-in-the-wrong-place files, you can set yourself up for down-the-road "fun" caused by "evil twins."
Personally, since you know the files and directories that got added, where, when and by whom, you could do something like this (command lines are off-the-top-of-my-head:
Get the list of files to copy/merge
cleartool find -type d -element "created_by(baduser) && created_since(25-Jul-2016) && !created_since(26-Jul-2016)" -print > dirlist.txt
cleartool find -type fl -element "created_by(baduser) && created_since(25-Jul-2016) && !created_since(26-Jul-2016)" -print > filelist.txt
Pull the directories over by merging the parent directories while CD'd/set in a view using the destination path. Not knowing the OS involved I can't say which way you would need to parse this. If you use perl, you can grab the offset of the last instance of the directory separator and use that in substr to get the parent directory path. In the windows command prompt, you can do something like this:
SET SRCDRIVE=D:
for /f "delims==" %x in (dirlist.txt) do cleartool co -nc %~px & cleartool merge -to %~px %SRCDRIVE%~px
for /f "delims==" %x in (dirlist.txt) do cleartool co -nc %~px & cleartool merge -to %~px\%~nx %SRCDRIVE%~px\%~nx
Yes, you can do all that in a single script, and do better error checking and not trying 40x to check out the same directory.
You might also be able to merge them to the 2.0 branch (using a view selecting the 2.0 branch). To identify the elements involved, you can run a 'cleartool find' command something like this:
% cd /vobs/myvob
% cleartool find -all -version 'brtype(1.0) && created_by(user_x)' -print
The 'created_since(date-time)' query might also be useful in the compound query.
Once you're convinced you have the right set of versions, you can use '-exec' in place of the '-print' to actually perform the merge. It might look something like this:
% cleartool find -all -version 'brtype(1.0) && created_by(user_x) && created_since(29-Jun)' -exec 'cleartool merge -to $CLEARCASE_PN -version $CLEARCASE_ID_STR'
If you're happy with the results, check everything in. Then you just have to decide if you need to remove the versions on the 1.0 branch (which you can do with another 'cleartool find ... -exec ...' command).

Git - how do I view the change history of a method/function?

So I found the question about how to view the change history of a file, but the change history of this particular file is huge and I'm really only interested in the changes of a particular method. So would it be possible to see the change history for just that particular method?
I know this would require git to analyze the code and that the analysis would be different for different languages, but method/function declarations look very similar in most languages, so I thought maybe someone has implemented this feature.
The language I'm currently working with is Objective-C and the SCM I'm currently using is git, but I would be interested to know if this feature exists for any SCM/language.
Recent versions of git log learned a special form of the -L parameter:
-L :<funcname>:<file>
Trace the evolution of the line range given by "<start>,<end>" (or the function name regex <funcname>) within the <file>. You may not give any pathspec limiters. This is currently limited to a walk starting from a single revision, i.e., you may only give zero or one positive revision arguments. You can specify this option more than once.
...
If “:<funcname>” is given in place of <start> and <end>, it is a regular expression that denotes the range from the first funcname line that matches <funcname>, up to the next funcname line. “:<funcname>” searches from the end of the previous -L range, if any, otherwise from the start of file. “^:<funcname>” searches from the start of file.
In other words: if you ask Git to git log -L :myfunction:path/to/myfile.c, it will now happily print the change history of that function.
Using git gui blame is hard to make use of in scripts, and whilst git log -G and git log --pickaxe can each show you when the method definition appeared or disappeared, I haven't found any way to make them list all changes made to the body of your method.
However, you can use gitattributes and the textconv property to piece together a solution that does just that. Although these features were originally intended to help you work with binary files, they work just as well here.
The key is to have Git remove from the file all lines except the ones you're interested in before doing any diff operations. Then git log, git diff, etc. will see only the area you're interested in.
Here's the outline of what I do in another language; you can tweak it for your own needs.
Write a short shell script (or other program) that takes one argument -- the name of a source file -- and outputs only the interesting part of that file (or nothing if none of it is interesting). For example, you might use sed as follows:
#!/bin/sh
sed -n -e '/^int my_func(/,/^}/ p' "$1"
Define a Git textconv filter for your new script. (See the gitattributes man page for more details.) The name of the filter and the location of the command can be anything you like.
$ git config diff.my_filter.textconv /path/to/my_script
Tell Git to use that filter before calculating diffs for the file in question.
$ echo "my_file diff=my_filter" >> .gitattributes
Now, if you use -G. (note the .) to list all the commits that produce visible changes when your filter is applied, you will have exactly those commits that you're interested in. Any other options that use Git's diff routines, such as --patch, will also get this restricted view.
$ git log -G. --patch my_file
Voilà!
One useful improvement you might want to make is to have your filter script take a method name as its first argument (and the file as its second). This lets you specify a new method of interest just by calling git config, rather than having to edit your script. For example, you might say:
$ git config diff.my_filter.textconv "/path/to/my_command other_func"
Of course, the filter script can do whatever you like, take more arguments, or whatever: there's a lot of flexibility beyond what I've shown here.
The closest thing you can do is to determine the position of your function in the file (e.g. say your function i_am_buggy is at lines 241-263 of foo/bar.c), then run something to the effect of:
git log -p -L 200,300:foo/bar.c
This will open less (or an equivalent pager). Now you can type in /i_am_buggy (or your pager equivalent) and start stepping through the changes.
This might even work, depending on your code style:
git log -p -L /int i_am_buggy\(/,+30:foo/bar.c
This limits the search from the first hit of that regex (ideally your function declaration) to thirty lines after that. The end argument can also be a regexp, although detecting that with regexp's is an iffier proposition.
git log has an option '-G' could be used to find all differences.
-G Look for differences whose added or removed line matches the
given <regex>.
Just give it a proper regex of the function name you care about. For example,
$ git log --oneline -G'^int commit_tree'
40d52ff make commit_tree a library function
81b50f3 Move 'builtin-*' into a 'builtin/' subdirectory
7b9c0a6 git-commit-tree: make it usable from other builtins
The correct way is to use git log -L :function:path/to/file as explained in eckes answer.
But in addition, if your function is very long, you may want to see only the changes that various commit had introduced, not the whole function lines, included unmodified, for each commit that maybe touch only one of these lines. Like a normal diff does.
Normally git log can view differences with -p, but this not work with -L.
So you have to grep git log -L to show only involved lines and commits/files header to contextualize them. The trick here is to match only terminal colored lines, adding --color switch, with a regex. Finally:
git log -L :function:path/to/file --color | grep --color=never -E -e "^(^[\[[0-9;]*[a-zA-Z])+" -3
Note that ^[ should be actual, literal ^[. You can type them by pressing ^V^[ in bash, that is Ctrl + V, Ctrl + [. Reference here.
Also last -3 switch, allows to print 3 lines of output context, before and after each matched line. You may want to adjust it to your needs.
Show function history with git log -L :<funcname>:<file> as showed in eckes's answer and git doc
If it shows nothing, refer to Defining a custom hunk-header to add something like *.java diff=java to the .gitattributes file to support your language.
Show function history between commits with git log commit1..commit2 -L :functionName:filePath
Show overloaded function history (there may be many function with same name, but with different parameters) with git log -L :sum\(double:filepath
git blame shows you who last changed each line of the file; you can specify the lines to examine so as to avoid getting the history of lines outside your function.

Remove unknown files in Bazaar

I have a bunch of unknown files in my Bazaar working tree that I no longer want. I can get a list of them using bzr stat, but I'd like an easy way to get rid of them. (I'd expect an option for bzr revert to do this, but I'm not finding one.)
I can always write a tiny script to parse the output of bzr stat and rm or mv the unknowns, but I thought something might already exist.
I have Bazaar (bzr) 1.13.1.
bzr clean-tree will get rid of all unknown files in a working tree. It also has switches to remove ignored files, merges backups and other types of unwanted files. See bzr clean-tree --usage for full details.
Edit to add: This is true for Bazaar 2.0.0, I'm not sure about 1.13
Made a script:
#!/usr/bin/env ruby
# Move unknown files in a Bazaar repository to the trash.
#
# Author: Benjamin Oakes
require 'fileutils'
TRASH_DIRECTORY = File.expand_path('~/.Trash/')
stdout = %x(bzr stat)
within = false
stdout.each_line do |line|
if line.match(/^unknown:$/)
within = true
next
elsif line.match(/^[a-z]+:$/i)
within = false
next
end
if within
FileUtils.move(line.match(/^\s+(.*?)$/)[1], TRASH_DIRECTORY)
end
end
I've only tested it a little, but it seems to work just fine. Please let me know if you find an issue via the comments.
On a separate topic, should I learn sed & awk? I tend to write these things using ruby -e "some ruby code".

Inverting a diff or patch || CVS diff

In CVS, my working copy (WC) is on a certain branch (which we'll call "foo"). There have been other changes checked into foo by another dev. I want to do a diff between my WC and the upstream state of foo. Normally, when working in the trunk (HEAD), I just do a cvs diff, and that's fine. But for some reason when doing a plain cvs diff in the branch, the diff is empty. When I try to use "cvs diff -r foo", the diff shows up, but it is inverted -- upstream additions are shown with minuses, and upstream removals are shown with pluses.
How can I either: (1) get CVS to diff "the other way" (plus for upstream additions), or (2) invert a patch (in general)?
maybe what you want can be done by using interdiff from the patchutils package.
I often use it this way to see what has changed on the TRUNK for a given file:
cvs diff -up -r1 givenfile | interdiff /dev/stdin /dev/null
If the principal purpose of this is to check "what's up" in the central repo, I suggest you get yourselves a functional CVS viewer/browser/web thingy where you can browse and see the latest changes before updating. But assuming all you have is command-line CVS, I will attempt to give you a solution anyway :)
So, what you have here is a branch foo that went from A -> B, where B is the state of the branch (on the server) after the other developer's checkin, and A is the state you last updated your working copy to.
When just doing a plain cvs diff in this situation, you'll see your local changes compared to A since A is what you have checked out. The local CVS state will show that each file comes from the A revision on the foo branch, and when diffing your CVS client will download that revision from the server. In your case I'm guessing you have no local changes since your cvs diff is empty.
Then, when you do a cvs diff -r foo you're diffing your local A (or A+changes) against the server's foo (which currently is at B) - and the changes required to get from the server's B to your A+changes is exactly the opposite of the other developer's check-in, plus your own local changes.
Now, if you really really want to know how B (or tip-of-foo) compares to A (the pristine version of whatever you currently have checked out), what I think you have to do is set a tag on your working copy, then diff that tag against the state of the branch. Something like this:
cvs tag pistos_temp1
cvs diff -r pistos_temp1 -r foo
# And clean up by deleting the tag afterwards:
cvs tag -d pistos_temp1
You can try export a file from the branch to some temporary file and then make diff between your working copy and this temp file. It seems to be the easiest way.