JGit log strange behavior after merge - git-merge

Found a strange behavior (bug?) in a log command.
The below test creates a repo, creates a branch, does some commits either to the created branch and to master, then merges master to the created branch. After merge it tries to calculate the number of commits between the branch and master. Because master has been already merged -- the branch is not behind the master, i.e. corresponding commit count should be 0.
public class JGitBugTest {
#Rule
public TemporaryFolder tempFolder = new TemporaryFolder();
#Test
public void testJGitLogBug() throws Exception {
final String BRANCH_NAME = "TST-2";
final String MASTER_BRANCH_NAME = Constants.MASTER;
File folder = tempFolder.newFolder();
// Create a Git repository
Git api = Git.init().setBare( false ).setDirectory( folder ).call();
Repository repository = api.getRepository();
// Add an initial commit
api.commit().setMessage( "Initial commit" ).call();
// Create a new branch and add some commits to it
api.checkout().setCreateBranch( true ).setName( BRANCH_NAME ).call();
api.commit().setMessage( "TST-2 Added files 1" ).call();
// Add some commits to master branch too
api.checkout().setName( MASTER_BRANCH_NAME ).call();
api.commit().setMessage( "TST-1 Added files 1" ).call();
api.commit().setMessage( "TST-1 Added files 2" ).call();
// If this delay is commented out -- test fails and
// 'behind' is equal to "the number of commits to master - 1".
// Thread.sleep(1000);
// Checkout the branch and merge master to it
api.checkout().setName( BRANCH_NAME ).call();
api.merge()
.include( repository.resolve( MASTER_BRANCH_NAME ) )
.setStrategy( MergeStrategy.RECURSIVE )
.call()
.getNewHead()
.name();
// Calculate the number of commits the branch behind of the master
// It should be zero because we have merged master into the branch already.
Iterable<RevCommit> iterable = api.log()
.add( repository.resolve( MASTER_BRANCH_NAME ) )
.not( repository.resolve( BRANCH_NAME ) )
.call();
int behind = 0;
for( RevCommit commit : iterable ) {
behind++;
}
Assert.assertEquals( 0, behind );
}
}
The above test fails, behind yields the number of commits in the master minus 1.
Moreover, if 'sleep' in line 43 is uncommented -- the bug will go away, and 'behind' is equal to 0.
What do I do wrong? Is it a bug in JGit library or in my code?

Running the code on Windows, I can reproduce what you describe.
This looks like a bug in JGit to me. I recommend to open a bugzilla or post your findings to the mailing list.

Related

IntelliJ IDEA LiveTemplate auto increment between usages

I am trying to make my life easier with Live Templates in intelliJ
I need to increment some param by 1 every-time I use the snippet.
So I tried to develop some groovyScript, and I am close, but my groovy capabilities keeps me back. the number is not incremented by 1, but incremented by 57 for some reason... (UTF-8?)
here is the script:
File file = new File("out.txt");
int code = Integer.parseInt(file.getText('UTF-8'));
code=code+1;
try{
if(_1){
code = Integer.parseInt(_1);
}
} catch(Exception e){}
file.text = code.toString();
return code
So whenever there's param passed to this script (with _1) the initial value is set, and otherwise simply incremented.
this script needs to be passed to the live template param with:
groovyScript("File file = new File(\"out.txt\");int code = Integer.parseInt(file.getText(\'UTF-8\'));code=code+1;String propName = \'_1\';if(this.hasProperty(propName) && this.\"$propName\"){code = Integer.parseInt(_1);};file.text =code.toString();return code", "<optional initial value>")

Switch / Checkout Branch ist not working

I'm using Version 0.19
I've a remote branch named 'dev'
after cloning i want to switch to this branch.
i found some code which performs an update to the branch. but for me it doesn't work.
I also try to run a checkout after this which also doesnt work.
When viewing the git log after the code i see the changesets of the master branch. But the local branch name is the name of the given name for the created branch (e.G. "dev")
what am i doing wrong?
private static Branch SwitchBranch(Repository repo, RepositoryProperties properties)
{
string branchname = properties.Branch;
Branch result = null;
if (!string.IsNullOrWhiteSpace(properties.Branch))
{
Branch remote = null;
foreach (var branch in repo.Branches)
{
if (string.Equals(branch.Name, "origin/" + branchname))
{
remote = branch;
break;
}
}
string localBranchName = properties.Branch;
Branch localbranch = repo.CreateBranch(localBranchName);
Branch updatedBranch = repo.Branches.Update(localbranch,
b =>
{
b.TrackedBranch = remote.CanonicalName;
});
repo.Checkout(updatedBranch);
result = updatedBranch;
}
return result;
}
The xml documentation of the CreateBranch() overload you're using states "Creates a branch with the specified name. This branch will point at the commit pointed at by Repository.Head".
From your question, it looks like you'd like this branch to also point to the same Commit than the remote tracking one.
As such, I'd suggest you to change your code as follows:
Branch localbranch = repo.CreateBranch(localBranchName, remote.Tip);
Be aware that you can only create the local branch once. So you're going to get an error the second time. At least, I did.
Branch localbranch = repo.Branches.FirstOrDefault(x => !x.IsRemote && x.FriendlyName.Equals(localBranchName));
if (localbranch == null)
{
localbranch = repo.CreateBranch(localBranchName, remote.Tip);
}
Branch updatedBranch = repo.Branches.Update(localbranch,
b =>
{
b.TrackedBranch = remote.CanonicalName;
});
repo.Checkout(updatedBranch);

Libgit2sharp Push Performance Degrading With Many Commits

The project I am working on uses GIT in a weird way. Essentially it writes and pushes one commit at a time. The project could result in one branch having hundreds of thousands of commits. When testing we found that after only about 500 commits the performance of the GIT push started to degrade. Upon further investigation using a process monitor we believe that the degradation is due to a walk of the entire tree for the branch being pushed. Since we are only ever pushing one new commit at any given time is there any way to optimize this?
Alternatively is there a way to limit the commit history to be something like 50 commits to reduce this overhead?
I am using LibGit2Sharp Version 0.20.1.0
Update 1
To test I wrote the following code:
void Main()
{
string remotePath = #"E:\GIT Test\Remote";
string localPath = #"E:\GIT Test\Local";
string localFilePath = Path.Combine(localPath, "TestFile.txt");
Repository.Init(remotePath, true);
Repository.Clone(remotePath, localPath);
Repository repo = new Repository(localPath);
for(int i = 0; i < 2000; i++)
{
File.WriteAllText(localFilePath, RandomString((i % 2 + 1) * 10));
repo.Stage(localFilePath);
Commit commit = repo.Commit(
string.Format("Commit number: {0}", i),
new Signature("TestAuthor", "TestEmail#Test.com", System.DateTimeOffset.Now),
new Signature("TestAuthor", "TestEmail#Test.com", System.DateTimeOffset.Now));
Stopwatch pushWatch = Stopwatch.StartNew();
Remote defaultRemote = repo.Network.Remotes["origin"];
repo.Network.Push(defaultRemote, "refs/heads/master:refs/heads/master");
pushWatch.Stop();
Trace.WriteLine(string.Format("Push {0} took {1}ms", i, pushWatch.ElapsedMilliseconds));
}
}
private const string Characters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
private static readonly Random Random = new Random();
/// <summary>
/// Get a Random string of the specified length
/// </summary>
public static string RandomString(int size)
{
char[] buffer = new char[size];
for (int i = 0; i < size; i++)
{
buffer[i] = Characters[Random.Next(Characters.Length)];
}
return new string(buffer);
}
And ran the process monitor found here:
http://technet.microsoft.com/en-us/sysinternals/bb896645.aspx
The time for each push ended up being generally low with large spikes in time increasing both in frequency and in latency. When looking at the output from the process monitor I believe these spikes lined up with a long stretch where objects in the .git\objects folder were being accessed. For some reason occasionally on a pull there are large reads of the objects which when looked at closer appears to be a walk through the commits and objects.
The above flow is a condensed version of the actual flow we were actually doing in the project. In our actual flow we would first create a new branch "Temp" from "Master", make a commit to "Temp", push "Temp", merge "Temp" with "Master" then push "Master". When we timed each part of that flow we found the push was by far the longest running operation and it was increasing in elapsed time as the commits piled up on "Master".
Update 2
I recently updated to use libgit2sharp version 0.20.1.0 and this problem still exists. Does anyone know why this occurs?
Update 3
We change some of our code to create the temporary branch off of the first commit ever on the "Master" branch to reduce the commit tree traversal overhead but found it still exists. Below is an example that should be easy to compile and run. It shows the tree traversal happens when you create a new branch regardless of the commit position. To see the tree traversal I used the process monitor tool above and command line GIT Bash to examine what each object it opened was. Does anyone know why this happens? Is it expected behavior or am I just doing something wrong? It appears to be the push that causes the issue.
void Main()
{
string remotePath = #"E:\GIT Test\Remote";
string localPath = #"E:\GIT Test\Local";
string localFilePath = Path.Combine(localPath, "TestFile.txt");
Repository.Init(remotePath, true);
Repository.Clone(remotePath, localPath);
// Setup Initial Commit
string newBranch;
using (Repository repo = new Repository(localPath))
{
CommitRandomFile(repo, 0, localFilePath, "master");
newBranch = CreateNewBranch(repo, "master");
repo.Checkout(newBranch);
}
// Commit 1000 times to the new branch
for(int i = 1; i < 1001; i++)
{
using(Repository repo = new Repository(localPath))
{
CommitRandomFile(repo, i, localFilePath, newBranch);
}
}
// Create a single new branch from the first commit ever
// For some reason seems to walk the entire commit tree
using(Repository repo = new Repository(localPath))
{
CreateNewBranch(repo, "master");
}
}
private const string Characters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
private static readonly Random Random = new Random();
/// <summary>
/// Generate and commit a random file to the specified branch
/// </summary>
public static void CommitRandomFile(Repository repo, int seed, string rootPath, string branch)
{
File.WriteAllText(rootPath, RandomString((seed % 2 + 1) * 10));
repo.Stage(rootPath);
Commit commit = repo.Commit(
string.Format("Commit: {0}", seed),
new Signature("TestAuthor", "TestEmail#Test.com", System.DateTimeOffset.Now),
new Signature("TestAuthor", "TestEmail#Test.com", System.DateTimeOffset.Now));
Stopwatch pushWatch = Stopwatch.StartNew();
repo.Network.Push(repo.Network.Remotes["origin"], "refs/heads/" + branch + ":refs/heads/" + branch);
pushWatch.Stop();
Trace.WriteLine(string.Format("Push {0} took {1}ms", seed, pushWatch.ElapsedMilliseconds));
}
/// <summary>
/// Create a new branch from the specified source
/// </summary>
public static string CreateNewBranch(Repository repo, string sourceBranch)
{
Branch source = repo.Branches[sourceBranch];
string newBranch = Guid.NewGuid().ToString();
repo.Branches.Add(newBranch, source.Tip);
Stopwatch pushNewBranchWatch = Stopwatch.StartNew();
repo.Network.Push(repo.Network.Remotes["origin"], "refs/heads/" + newBranch + ":refs/heads/" + newBranch);
pushNewBranchWatch.Stop();
Trace.WriteLine(string.Format("Push of new branch {0} took {1}ms", newBranch, pushNewBranchWatch.ElapsedMilliseconds));
return newBranch;
}
/// <summary>
/// Get a Random string of the specified length
/// </summary>
public static string RandomString(int size)
{
char[] buffer = new char[size];
for (int i = 0; i < size; i++)
{
buffer[i] = Characters[Random.Next(Characters.Length)];
}
return new string(buffer);
}

Why batch jobs working on one server but not on other one?

I have same code on two servers.
I have job for adding batch job to the queue
static void Job_ScheduleBatch2(Args _args)
{
BatchHeader batHeader;
BatchInfo batInfo;
RunBaseBatch rbbTask;
str sParmCaption = "My Demonstration (b351) 2014-22-09T04:09";
SysRecurrenceData sysRecurrenceData = SysRecurrence::defaultRecurrence();
;
sysRecurrenceData = SysRecurrence::setRecurrenceStartDateTime(sysRecurrenceData, DateTimeUtil::utcNow());
sysRecurrenceData = SysRecurrence::setRecurrenceUnit(sysRecurrenceData, SysRecurrenceUnit::Minute,1);
rbbTask = new Batch4DemoClass();
batInfo = rbbTask .batchInfo();
batInfo .parmCaption(sParmCaption);
batInfo .parmGroupId(""); // The "Empty batch group".
batHeader = BatchHeader ::construct();
batHeader .addTask(rbbTask);
batHeader.parmRecurrenceData(sysRecurrenceData);
//batHeader.parmAlerts(NoYes::Yes,NoYes::Yes,NoYes::Yes,NoYes::Yes,NoYes::Yes);
batHeader.addUserAlerts(curUserId(),NoYes::No,NoYes::No,NoYes::No,NoYes::Yes,NoYes::No);
batHeader .save();
info(strFmt("'%1' batch has been scheduled.", sParmCaption));
}
and I have a batch job
class Batch4DemoClass extends RunBaseBatch
{
int methodVariable1;
int metodVariable2;
#define.CurrentVersion(1)
#localmacro.CurrentList
methodVariable1,
metodVariable2
endmacro
}
public container pack()
{
return [#CurrentVersion,#CurrentList];
}
public void run()
{
// The purpose of your job.
info(strFmt("epeating batch job Hello from Batch4DemoClass .run at %1"
,DateTimeUtil ::toStr(
DateTimeUtil ::utcNow())
));
}
public boolean unpack(container _packedClass)
{
Version version = RunBase::getVersion(_packedClass);
switch (version)
{
case #CurrentVersion:
[version,#CurrentList] = _packedClass;
break;
default:
return false;
}
return true;
}
On one server it do runs and in batch history I can see it is saving messages to the batch log and on the other server it does nothing. One server is R2 (running) and R3 (not running).
Both codes are translated to CIL. Both servers are Batch server. I can see the batch jobs in USMF/System administration/Area page inquries. Only difference I can find is that jobs on R2 has filled AOS instance name in genereal and in R3 it is empty. In R2 I can see that info messages in log and batch history but there is nothing in R3.
Any idea how to make batch jobs running?
See how to Configure an AOS instance as a batch server.
There are 3 preconditions:
Marked as a batch server
Time interval set correctly
Batch group set correctly
Update:
Deleting the user of a batch job may make the batch job never complete. Once the execute queue has filled, no further progress will happen.
Deleting the offending batch jobs is problematic, as only the owner can do so! Then consider changing BatchJob.aosValidateDelete.
Yes, worth a try to clear the tables, also if you could provide a screenshot of the already running batchjobs and their status, that might be of help further.

Update a DynamicContent item of a dynamic module in Sitefinity

I am trying to update a DynamicContent Property of a module using the following:
DynamicModuleManager dynamicModuleManager = DynamicModuleManager.GetManager();
Type pollanswerType = TypeResolutionService.ResolveType("Telerik.Sitefinity.DynamicTypes.Model.Poll.Pollanswer");
Guid pollanswerID = new Guid(answerID);
// This is how we get the pollanswer item by ID
DynamicContent pollanswerItem = dynamicModuleManager.GetDataItem(pollanswerType, pollanswerID);
pollanswerItem.SetValue("VoteCount", int.Parse(pollanswerItem.GetValue("VoteCount").ToString()) + 1);
dynamicModuleManager.SaveChanges();
Basically getting the current Property value and incrementing it by 1
and calling SaveChanges()
the code runs without errors but it doesn't update the value when I check it from the Back End of Sitefinity.
Any suggestions?
The problem might be caused by the pollanswerID that you are passing.
If the pollanswerID is the id of the live version of the content item then the value wouldn't be set.
Make sure you set the field value to the of master version of the content type not the live one.
In case you don't know the id of the master version of the content type you can get the master content item by the id of the live version of the content type
var masterItem = dynamicModuleManager.GetDataItems(pollanswerType).Where(dynItem => dynItem.Id == pollanswerItem.OriginalContentId).FirstOrDefault();
if (masterItem != null)
{
masterItem.SetValue("VoteCount", int.Parse(masterItem.GetValue("VoteCount").ToString()) + 5);
}
you should be always doing this
Get Master
Checkout Master
Checkin Master
Save Changes
Publish changes – this will update live.
bookingItemLive is the live record
var bookingItemMaster = dynamicModuleManager.Lifecycle.Edit(bookingItemLive) as DynamicContent;
//Check out the master to get a temp version.
DynamicContent bookingItemTemp = dynamicModuleManager.Lifecycle.CheckOut(bookingItemMaster) as DynamicContent;
//Make the modifications to the temp version.
bookingItemTemp.SetValue("CleanerId", cleanerId);
bookingItemTemp.SetValue("SubCleanerId", subCleanerId);
bookingItemTemp.LastModified = DateTime.UtcNow;
//Checkin the temp and get the updated master version.
//After the check in the temp version is deleted.
bookingItemMaster = dynamicModuleManager.Lifecycle.CheckIn(bookingItemTemp) as DynamicContent;
dynamicModuleManager.SaveChanges();
//Publish the item now
ILifecycleDataItem publishedBookingItem = dynamicModuleManager.Lifecycle.Publish(bookingItemMaster);
bookingItemMaster.SetWorkflowStatus(dynamicModuleManager.Provider.ApplicationName, "Published");
#Joseph Ghassan: You can follow below step.
Step 1: Get Live
var bookingItemLive= manager.GetDataItem(ModuleType, GuidId);
Step 2: Get Master
var bookingItemMaster = manager.Lifecycle.GetMaster(bookingItemLive) as DynamicContent;
Step 2: Checkout Master --> will be created a draft item( you will update data by draft)
if (bookingItemMaster == null)
{
return new HttpResponseMessage
{
Content = new JsonContent(new { Result = false })
};
}
var bookingItemDraff = manager.Lifecycle.CheckOut(bookingItemMaster) as DynamicContent;
//Make the modifications to the temp version.
bookingItemDraff.SetValue("CleanerId", cleanerId);
bookingItemDraff.SetValue("SubCleanerId", subCleanerId);
bookingItemDraff.LastModified = DateTime.UtcNow;
Step 3: Checkin Master
// Now we need to check in, so the changes apply
var checkInItem = manager.Lifecycle.CheckIn(bookingItemDraff);
Step 4: Publish changes
manager.Lifecycle.Publish(checkInItem);
Step 5: Save Changes - this will save to Database and update live.
bookingItemDraff.SetWorkflowStatus(manager.Provider.ApplicationName, CustomFieldName.PublishedStatus);
manager.SaveChanges();