How to realize the "cp -u" function in a clearcase vob? - linux

We have two vobs which are "voba" and "vobb". And there is a directory "abc" in both vob and contains the same .h / .cpp files.
Usually, the files in "abc" dir in "voba" are updated quite frequently. And from time to time, I would like to update all files in "abc of vobb" from "abc of voba", which means:
Checkout the updated files in vobb.abc, overwrite them and then check in.
Copy the newly created files to vobb.abc, create element.
Delete the deleted files in vobb.abc by corrspoding to voba.abc.
If it is a common linux directory, I think cp -u and achieve that. But when it comes to the clearcase, I can only do the above 1-3 by hand.
Is there any easy way to finish that update automatically?

This is called in ClearCase a clearfsimport (potentially used with the -mirror option)
Since the elements in the directories abc of the two vobs are completely different (different oid, with different history), what you can do is import the content of abc from one vob into another: clearfsimport will automatically checkout, update and checkin only the files that have evolved in the source, and need to be updated in the destination.
Note, this recent thread (March 2013) also points out to the perl script ClearCase::SyncTree
It is superior to clearfsimport in many respects, especially in its evil twin avoidance (it will try with the proper options to link suitable entries from non visible versions).
Description:
This module provides an infrastructure for programs which want to synchronize a set of files, typically a subtree, with a similar destination subtree in VOB space. The enclosed synctree script is an example of such a program.
The source area may be in a VOB or may be a regular filesystem; the destination area must be in a VOB.
Methods are supplied for adding, subtracting, and modifying destination files so as to make that area look identical to the source.
Symbolic links are supported, even on Windows (of course in this case the source filesystem must support them, which is only likely in the event of an MVFS->MVFS transfer). Note that the text of the link is transported verbatim from source area to dest area; thus relative symlinks may no longer resolve in the destination.

Related

Is there a way to still use symbolic link for .gitignore? And why it's not supported anymore as a symbolic link?

I have a central .gitignore on my laptop and for each project that I create, I create a symbolic link to that central file so that I can keep a uniform policy across all of my projects.
All of my projects are like each other (technology-wise) and it makes sense to have a central .gitignore to reduce the burden of maintenance.
However, recently I see this message:
warning: unable to access '.gitignore': Too many levels of symbolic links
And as I searched, it seems that from git 2.3 upwards they have decided to not support the symbolic link.
I have two questions. First, is there a way to force git to support symbolic links for .gitignore? And why on Earth do they not support it anymore? Does it not make sense to reuse code? Is half of linux not reused through symbolic links?
First, is there a way to force git to support symbolic links for .gitignore?
No.
And why on Earth do they not support it anymore?
The gitattributes documentation now (as of Git 2.32) says this near the end:
NOTES
Git does not follow symbolic links when accessing a .gitattributes file in the working tree. This keeps behavior consistent when the file is accessed from the index or a tree versus from the filesystem.
While I'm not 100% sold on the reasoning here myself, it does make sense. (It seems to me that Git could just stuff the content of the .gitattributes file into the index and hence into the commits, although this would mean that on checkout it would destroy the symlink.)
Optional further reading / background
First, let's describe what a "symbolic link" is in the first place. To do this we must define what a file is (which is a pretty big job, so we'll just do very light bit of coverage): A file is a named entity, typically found in a file system (systematic collection of files), that store data for later retrieval. Being a named entity, a file has a name: for instance, README.txt, Makefile, and .gitconfig are all file names. Different OSes place different constraints on file names (e.g., Windows refuses to store a colon : character in a file name or create any file named aux with or without a suffix, so that you cannot have a C or C++ include file named aux.h or aux.hpp). Git itself places very few constraints on file names: they can contain almost any character except an ASCII NUL (b'\0' in Python, \0 in C, etc.), and forward slashes / are slightly special, but other than that a name character is just a name character and there are very few restrictions.1
On most real OSes, files can have "types". The exact mechanisms here rapidly become OS-specific and can get very complicated,2 though traditional Unix-like hierarchical file systems just have a few types: "directory", "file", "block or character device", "symbolic link", and the like. Symbolic links are in fact one of these types.
A symbolic link is a type of file in which the file's content is another file name. This file name, on a Unix-like file system, can be absolute (/home/john/somefile, /Users/torek/somefile) or relative (./somefile, ../../somefile). On these systems, opening a symbolic link results in opening the file whose name is provided by the symbolic link's content. To read the content of the symbolic link—that is, to find out what file name the link contains—we use a different operation: readlink instead of open, for instance. Modern Unix systems also have an O_NOFOLLOW flag that can be used to forbid the open system call from following the link.3
The way Git stores a symlink is as a special mode object in a commit: ordinary files are either mode 100644, meaning a non-executable file, or mode 100755, meaning an executable file. A symbolic link is stored as mode 120000 and Git stores the target name, found by calling readlink, as the content.4
1The one peculiar restriction is that you're not allowed to store anything named .git, in any mix or upper and/or lower case. This .git restriction actually applies to "name components" which are the parts between forward slashes. Due to Windows being Windows, Git-on-Windows will turn backwards slashes into forwards ones as necessary, and then places the restriction on the components.
2Traditional OSes from the 1960s through 1980s, for instance, may impose things called access methods based in part on file types. Unix simplified things a lot here.
3This is sometimes important for various security aspects. The details are beyond the scope of this article.
4These odd mode values correspond closely to the struct stat st_mode field in a Unix/Linux stat system call. That's because when Linus Torvalds first wrote the initial versions of Git, he was dealing with it—at least in part—as a kind of file system. The ability to store full Unix file modes (9 bits of rwxrwxrwx flags) was left in, and initially Git actually stored group write permissions, but this turned out to be a mistake and was removed before the first public release. The 100000 part is S_IFREG, "Stat: Inode Format REGular file". The 120000 found in a Git symbolic link is S_IFLNK, or "Stat: Inode Format symbolic LiNK". We also have mode 040000 for directories from S_IFDIR, which should now be obvious. However, Git can't store a mode 040000 entry in its index / staging-area, for no particularly good reason, which leads to the problem described in How can I add a blank directory to a Git repository?
In other words, a symbolic link means "use another file"
Wherever a symbolic link is found, it means read or write some other file. So if README.txt is a symbolic link reading /tmp/fooledyou, any attempt to read README.txt actually reads /tmp/fooledyou instead; any attempt to write README.txt actually writes to /tmp/fooledyou.
Consider, though, when this redirection—from README.txt to /tmp/fooledyou—occurs. It doesn't happen at the time you make the symbolic link itself. You can create this README.txt file last year. When I go to read README.txt, that's when the redirection occurs. So if you've changed /tmp/fooledyou since you created README.txt, I get the modern version, not the old one.
That, of course, is precisely why you wanted the symbolic link in the first place:
All of my projects are like each other (technology-wise) and it makes sense to have a central .gitignore to reduce the burden of maintenance.
In other words, you wanted to have one .gitignore, that is not version controlled, that always reflects what should be ignored based on what you learned up until right now, regardless of when it is that "right now" is.
This is the opposite of Git's normal purpose, which is to store a full snapshot of what your project looked like "back then", whenever "back then" was: the time at which you made a git commit snapshot.
My suggested possibility above is that when you run:
git add .gitignore
to update Git's idea of what should go in the .gitignore file that goes in the next commit, Git could follow the .gitignore indirection at that time, read the contents of the target of the symbolic link, and prepare that to be committed. You'd then make the commit—the snapshot and metadata—such that if, next year, you extract this particular historical commit, you'll get the historical snapshot, including the historical .gitignore.
The drawback to this is that by extracting the historical .gitignore, you "break the link": .gitignore is no longer a symbolic link at all. Instead, it is now an ordinary file, containing the historical snapshot. There's no way to get the link back except to remove the ordinary file and create a new symbolic link.
Before Git version 2.32, Git would notice when .gitignore was a symbolic link and would store, in its index / staging-area, the fact that .giginore was a symlink (mode 120000) and use the readlink system call to find the target of the symlink, and store that in the commit. Running git commit then makes a snapshot that, when extracted, creates .gitignore as a (new) symbolic link: the existing file-or-symlink is removed, and the new one is installed instead. It redirects, in the usual symlink fashion, to the saved (committed) historical location—even if that's wrong now.
As of Git version 2.32, Git will still store a symbolic link .gitignore file:
$ mkdir z; cd z
$ ../git --version
git version 2.36.1.363.g9c897eef06
$ ../git init
[messages snipped; branch renamed to main, also snipped]
$ echo testing > README
$ ln -s foo .gitignore
$ git add README .gitignore
$ git commit -m initial
[main (root-commit) 08c6626] initial
2 files changed, 2 insertions(+)
create mode 120000 .gitignore
create mode 100644 README
$ ../git ls-tree HEAD
120000 blob 19102815663d23f8b75a47e7a01965dcdc96468c .gitignore
100644 blob 038d718da6a1ebbc6a7780a96ed75a70cc2ad6e2 README
The same reasoning—that a Git commit, once it's made and stuffed into a repository, may contain a symbolic link that is no longer valid or correct—explains why Git 2.32 also refuses to follow .gitattributes and .mailmap files. Note that commands like git archive generally use the commit's version of .gitattributes to control archive substitutions, so a symbolic link stored in the repository is useless unless the target of the symbolic link is somehow correct. The repository and its commits get shipped around from one machine to another, but the targets of any committed symlinks in many cases don't.

Unix create multiple files with same name in a directory

I am looking for some kind of logic in linux where I can place files with same name in a directory or file system.
For e.g. i create a file abc.txt, so the next time if any process creates abc.txt it should automatically check and make the file named as abc.txt.1 should be created, then next time abc.txt.2 and so on...
Is there a way to achieve this.
Any logic or third party tools are also welcomed.
You ask,
For e.g. i create a file abc.txt, so the next time if any process
creates abc.txt it should automatically check and make the file named
as abc.txt.1 should be created
(emphasis added). To obtain such an effect automatically, for every process, without explicit provision by processes, it would have to be implemented as a feature of the filesystem containing the files. Such filesystems are called versioning filesystems, though typically the details are slightly different from what you describe. Most importantly, however, although such filesystems exist for Linux, none of them are mainstream. To the best of my knowledge, none of the major Linux distributions even offers one as a distribution-supported option.
Although it's a bit dated, see also Linux file versioning?
You might be able to approximate that for many programs via a customized version of the C standard library, but that's not foolproof, and you should not expect it to have universal effect.
It would be an altogether different matter for an individual process to be coded for such behavior. It would need to check for existing files and choose an appropriate name when opening each new file. In doing so, some care needs to be taken to avoid related race conditions, but it can be done. Details would depend on the language in which you are writing.
You can use BASH expression to achieve this. For example if I wanted to make 10 files all with the same name, but having a unique number value I would do the following:
# touch my_file{01..10}.txt
This would create 10 files starting at 01 all the way to 10. This method is also hand for looping over files in a sequence or if your also creating directories.
Now if i am reading you question right your asking that if you move a file or create a file in a directory. you would want the a script to automatically create a new file for you? If that is the case then just use a test and if there is a file move that file and mark it. Me personally I use time stamps to do so.
Logic:
# The [ -f ] tests if the file is present
if [ -f $MY_FILE_NAME ]; then
# If the file is present move the file and give it the PID
# That way the name will always be unique
mv $MY_FILE_NAME $MY_FILE_NAME_$$
mv $MY_NEW_FILE .
else
# Move or make the file here
mv $MY_NEW_FILE .
fi
As you can see the logic is very simple. Hope this helps.
Cheers
I don't know about Your particular use case, but You may try to look at logrotate:
https://wiki.archlinux.org/index.php/Logrotate

How to reference or link files and folders inside a git repository to match these criteria?

I've encountered a problem long time ago which I couldn't solve, but I'm curious whether it's possible to fulfill ALL of the below listed criteria at once or not.
The solution what I was looking for can:
somehow refer to an existing file or folder from another folder of the same git repo
basically reach the content of the file or folder from another subfolder, see the content(s) as if they were on the another path as well
e.g.: if ./path/to/folder is referred from ./another_path/different_folder, then every file in ./path/to/folder/* is visible on path ./another_path/different_folder/*
e.g.: if ./path/to/file is referred by ./another_path/different_file, then by reading/writing content of the different_file, the original file is read/modified
store the referred file only once in git repo
don't want to make a copy of the file to another path and maintain changes in both files simultaneously
be able to use multiple references for a single file
be able to use relative paths
make it work on both Windows and Linux
As if I can remember, some of the problems were while experimenting with this:
the paths were broken after the repository was pulled to a different path (I assume they were not relative, but absolute)
the Windows style links are special files, were not working on Linux
the symlinks can't handle relative paths correctly on the Windows system
the hardlinks resulted duplicating files in Windows
(I can't remember exactly which if these might be incorrect, but I'll experiment with the problem again and try to update this question.)
Is there any workaround for this problem?
Thank you for any help!
Please note (in case you would like to mark this question as a duplicate), that there are other similar questions here, but none of those questions define this set of the criteria, therefore it can't be a duplicate.

shell script to create backup file when creating new file in particular directory

Recently I was asked the following question in an interview.
Suppose I try to create a new file named myfile.txt in the /home/pavan directory.
It should automatically create myfileCopy.txt in the same directory.
A.txt then it automatically creates ACopy.txt,
B.txt then BCopy.txt in the same directory.
How can this be done using a script? I may know that this script should run in crontab.
Please don't use inotify-tools.
Can you explain why you want to do?
Tools like VIM can create a backup copy of a file you're working on automatically. Other tools like Dropbox (which works on Linux, Windows, and Mac) can version files, so it backs up all the copies of the file for the last 30 days.
You could do something by creating aliases to the tools you use for creating these file. You edit a file with the tools you tend to use, and the alias could create a copy before invoking a tool.
Otherwise, your choice is to use crontab to occasionally make backups.
Addendum
let me explain suppose i have directory /home/pavan now i create the file myfile.txt in that directory , immediately now i should automatically generate myfileCopy.txt file in the same folder
paven
There's no easy user tool that could do that. In fact, the way you stated it, it's not clear exactly what you want to do and why. Backups are done for two reasons:
To save an older version of the file in case I need to undo recent changes. In your scenario, I'm simply saving a new unchanged file.
To save a file in case of disaster. I want that file to be located elsewhere: On a different computer, maybe in a different physical location, or at least not on the same disk drive as my current file. In your case, you're making the backup in the same directory.
Tools like VIM can be set to automatically backup a file you're editing. This satisfy reason #1 stated above: To get back an older revision of the file. EMACs could create an infinite series of backups.
Tools like Dropbox create a backup of your file in a different location across the aether. This satisfies reason #2 which will keep the file incase of a disaster. Dropbox also versions files you save which also is reason #1.
Version control tools can also do both, if I remember to commit my changes. They store all changes in my file (reason #1) and can store this on a server in a remote location (reason #2).
I was thinking of crontab, but what would I backup? Backup any file that had been modified (reason #1), but that doesn't make too much sense if I'm storing it in the same directory. All I would have are duplicate copies of files. It would make sense to backup the previous version, but how would I get a simple crontab to know this? Do you want to keep the older version of a file, or only the original copy?
The only real way to do this is at the system level with tools that layer over the disk IO calls. For example, at one location, we used Netapps to create a $HOME/.snapshot directory that contained the way your directory looked every minute for an hour, every hour for a day, and every day for a month. If someone deleted a file or messed it up, there was a good chance that the version of the file exists somewhere in the $HOME/.snapshot directory.
On my Mac, I use a combination of Time Machine - which backs up the entire drive every hour, and gives me a snapshot of my drive that stretches back over a year and a half) and Dropbox which keeps my files stored in the main Dropbox server somewhere. I've been saved many times by that combination.
I now understand that this was an interview question. I'm not sure what was the position. Did the questioner want you to come up with a system wide way of implementing this, like a network tech position, or was this one of those brain leaks that someone comes up with at the spur of the moment when they interview someone, but were too drunk the night before to go over what they should really ask the applicant?
Did they want a whole discussion on what backups are for, and why backing up a file immediately upon creation in the same directory is a stupid idea non-optimal solution, or were they attempting to solve an issue that came up, but aren't technical enough to understand the real issue?

How to create a copy of a directory on Linux with links

I have a series of directories on Linux and each directory contains lots of files and data. The data in those directories are automatically generated, but multiple users will need to perform more analysis on that data and generate more files, change the structure, etc.
Since these data directories are very large, I don't want several people to make a copy of the original data so I'd like to make a copy of the directory and link to the original from the new one. However, I'd like any changes to be kept only in the new directory, and leave the original read only. I'd prefer not to link only specific files that I define because the data in these directories is so varied.
So I'm wondering if there is a way to create a copy of a directory by linking to the original but keeping any changed files in the new directory only.
It turns out this is what I wanted to:
cp -al <origdir> <newdir>
It will copy an entire directory and create hard links to the original files. If the original file is deleted, the copied file still exists, and vice-versa. This will work perfectly, but I found newdir must not already exist. As long as the original files are read-only, you'll be able to create an identical, safe copy of the original directory.
However, since you are looking for a way that people can write back changes, UnionFS is probably what you are looking for. It provides means to combine read-only and read-write locations into one.
Unionfs allows any mix of read-only and read-write branches, as well as insertion and deletion of branches anywhere in the fan-out.
Originally I was going to recommend this (I use it a lot):
Assuming the permissions aren't an issue (e.g. only reading is required) I would suggest to bind-mount them into place.
mount -B <original> <new-location>
# or
mount --bind <original> <new-location>
<new-location> must exist as a folder.

Resources