问:
How is it possible to check if there are untracked/ignored files on stash which does not exist anymore locally? ( git, linux )
I was confused, and I called git stash --all and git stash apply stash@{...} multiple times, and also deleted some of the untracked/ignored files.

How is it possible to check, if there are files which exist in one of the stashes, but not locally?

答:
TL;DR

You may want to use git diff --name-only --diff-filter=D stash@{number}^3 on each valid stash@{number}.  (To get a list of stashes, use git stash list.)

You may want to use git show --name-only stash@{number}^3 on each valid stash@{number}.  Note that this is git show stash@..., not git stash show.

To understand which and why, read on.

Long

What git stash does is a bit complicated, but it can be summarized pretty simply:

git stash push (or the old spelling, git stash save) makes two or three commits, with none of the commits it makes being on any branch.  Then it runs git reset or git clean or some combination of those, depending on flags used.

git stash apply merges some or all of the two or three commits in some stash with your existing index and work-tree.

git stash pop means run git stash apply, and then if that claims to succeed, run git stash drop.

Unfortunately, the above is actually pretty complex—it requires that you understand Git's usage of the index, for one thing–and yet is incomplete.  It says that git stash push makes two commits (or sometimes three), but it does not say what is in those commits, nor what form they have in your repository.  For the simplest usage of git stash, none of those matter too much, but for your case, they are crucial.

Commits

I'll just mention these briefly since, aside from the ones that git stash makes, we're not too concerned with them.  Each commit holds a complete snapshot of files.  Exactly which files, we'll see in a moment.  Along with the snapshot, the commit contains some metadata, including who made the commit, when (date-and-time-stamp), and why (log message).  Each commit has a unique hash ID, and as part of the metadata, each commit includes the hash ID of its parent—a link back to the previous commit.

A merge commit has links back to two or more parents.  Commits that are linked this way are normally closely related—which is why the linkage is parent/child, after all—but unlike the snapshot-plus-metadata part, there's no hard requirement that the files in any one commit relate much to those in any other.  We'll see that in a moment, with the stash commits, too.

Besides being identified by their hash IDs, commits are mostly permanent—though of course stash commits are intended to be non-permanent and will eventually go away after being dropped—and are completely read-only.  This means that they cannot be used to do any new work, which is why Git has more than just commits.  This is why you need a work-tree.

The index and the work-tree

As we just noted, the commits are read-only.  Not only that, the files stored in each commit are in a special, compressed, read-only format.  This means two or more commits can share a file that's the same in both commits, which in turn means that even if you commit some version of a file hundreds of times, Git only has to store it once.  I like to refer to these internal format files as freeze-dried.

In order for you to actually use or change your files, Git has to rehydrate them, turning them back into ordinary files that you can read and write.  The area in which commits are rehydrated for your use is your work-tree.  Git could stop here—with frozen commits holding dehydrated files, as permanent as the commits themselves, plus temporary, ephemeral, but useful work-tree files.  Other version control systems do stop here: you have, at any time, the freeze-dried copy of a file in the current commit, plus the useful one in the work-tree.  But for various reasons, Git adds a third copy of the file.  This extra copy sits between the commit and the work-tree, in what Git calls, variously, the index or the staging area.

The extra copy of each file that's in the index, between the frozen dehydrated copy in the current commit and the useful copy in the work-tree, is also in the dehydrated form.  The key difference between it and the current-commit copy is that it's not read-only.  You can overwrite it—though technically this just moves the previous one out of the way—with a new freeze-dried copy at any time.  That's what git add does: it freeze-dries the work-tree copy and uses that to overwrite the index copy.

This is why you have to git add files all the time.  They're already there, in the index, ready to commit—but they match the one that came out of the last commit.  You've modified the work-tree copy, but the frozen copy hasn't changed—of course not, it's frozen—and neither has the index copy, which matches the committed copy.  So now you have to re-compress the updated file and replace the index copy.  You run git add updated.ext and Git does just that.  Now your index and work-tree match, and differ from the frozen copy.

When you run git commit, Git looks not at your work-tree but at your index.  Whatever is in your index right then, Git packs those (already freeze-dried) files into a new commit, and that new commit becomes your current commit.  Now your index and commit match, because the new commit was made from the index.

This is also what determines whether a file is tracked.  If there is a copy in the index, the file is tracked.  The tracked copy—the one in the index—will be in the next commit, if you make it right now.  If you have a file in your work-tree that isn't in your index, that file is untracked.  That file won't be in the next commit, if you make it right now.  Hence the index is, in a way, the proposed next commit.  Every time you update it with git add, you're proposing to commit something slightly different.

Files that are untracked normally make various Git commands—especially git status—complain.  You can shut up these complaints, and also make git add --all not copy the files into the index, by listing some or all of these files in a .gitignore.  Note that listing a tracked file has no effect: it's already there in the index, so there's no question of ignoring it: it's not ignored.  Being listed in .gitignore only affects untracked files, and basically just makes it hard to accidentally track them, and shuts up git status about them.

You can put new files into the index at any time, using git add.  If the file wasn't there before, git add creates it in the index, rather than displacing the previous copy.  You can also remove files from the index at any time, using either git rm—this removes the file from the index and the work-tree—or git rm --cached, which removes the file from the index only.  At git commit time, it doesn't matter how a file is or isn't in the index, only whether it is or is not there, and if it is there, with what freeze-dried content.

It's worth a brief look at how git commit makes a new commit now.  When you run git commit, as we already mentioned, Git stuffs all the tracked files into a new commit.  First, though, Git gathers up the metadata: your name (from user.name), your email address (from user.email), the current date-and-time, and your log message.  Git also knows which commit is the current commit.  That commit's hash ID goes into the parent hash ID for the new commit.  And then Git saves the index and makes the commit, which automatically gets a new, unique hash ID.  As the last step of git commit, Git then writes the new commit's hash ID into the current branch name.

Hence if you used to have:

```<code>...--F--G--H   <-- master (HEAD)
</code>```

with commit H as the current commit, and you've just made new commit I, new commit I points back to H, and Git has shoved the hash ID of I into the branch name master, so now you have:

```<code>...--F--G--H--I   <-- master
</code>```

Now we can look at what git stash push does

When git stash builds a new stash without --all, it:

Writes out the index as a commit.  This is really easy since that's what git commit already does.  All Git has to do is not update the name master (and supply a log message for you, which it does).  Let's write out a commit i (lowercase) and not put it on master.  Instead, we'll remember it with a temporary variable:

```<code>...--F--G--H   <-- master
           |
           i   <-- $tempvar
</code>```

Writes out the work-tree as a commit.  This is tricky to do efficiently, and also requires another special trick at the end.  Without going into the details of how git stash manages writing the work-tree, it's worth saying that this only writes tracked files.  The trick at the end is that git stash sets things up so that this new commit, which we'll call w, has two parents instead of one.  The first parent of w will be H and the second parent of w will be i:

```<code>...--F--G--H   <-- master
           |\
           i-w   <-- stash
</code>```

With these two commits written out, Git updates the special name refs/stash to remember the hash ID of commit w.

This stash has no untracked files, regardless of whether they're ignored.  Commit i was made from the index, so it has no untracked files by definition.  The process that Git uses to make w only stores files that are in the index, so it has no untracked files either.

If you use git stash push --all, git stash push --include-untracked, or the git stash save flavors of these same commands, Git modifies the saving process a bit.  It makes commit i as usual, but then it makes a commit I call u, to hold the untracked files.  This extra commit either holds just the untracked files, excluding the untracked-and-ignored files, or it holds all the untracked files including the ignored ones.  This commit has no parent listed (which is a good trick, but easy to do when you use the Git plumbing commands, as git stash did before it was converted to C code recently); it just floats out there on its own:

```<code>...--F--G--H   <-- master
           |
           i   <-- $i_commit

           u   <-- $u_commit
</code>```

Now git stash save goes back to its main path and makes commit w, but this time it gives w three parents: the current commit H, the index commit i, and the untracked-files commit u:

```<code>...--F--G--H   <-- master
           |\
           i-w   <-- stash
            /
           u
</code>```

Quick recap: what's in i, w, and u

Commit i holds the index state.  There are, by definition, no untracked files in i.  Commit w holds the work-tree state, again without untracked files.  If commit u exists—it's optional, after all—it holds the untracked files, but no tracked files: the stash code parsimoniously saves those only in i and w.

Now git stash push cleans up

Having saved files in two or three commits, the last step of git stash push is to reset the index and work-tree.  If you told git stash to create commit u, it also removes from the work-tree any file it saved in commit u.

The reset of index and work-tree is normally done by a simple git reset --hard.  This leaves the index and work-tree in a state that matches the current commit H.  If you made the u commit, its files are now gone from the work-tree, otherwise those files are untouched in the work-tree.

However, git stash push (unlike git stash save) has the ability to reset less than the entire work-tree.  In that case, it's all done by a more complex bit of code.  You can also (well, instead) throw in the option --keep-index, in which case, instead of git reset --hard or similar, Git checks out what's in commit i, so that the work-tree matches i.  (It leaves the index itself alone, so i and the index continue to match.)  None of this affects your immediate task, but all of it affects the ability to restore one of these stashes.

Previous stashes get "stacked"

When git stash push is done, the new stash is the one identified by refs/stash, or just stash for short.  You can also describe this as stash@{0}, if you like.  Any existing stashes are moved up one, to stash@{1}, stash@{2}, and so on: what was stash@{1} becomes stash@{2}, etc.

The mechanism behind this is Git's reflogs, which apply to all references: branches have master@{1}, master@{2}, and so on, too.  The stash code just (ab?)uses these to implement the stash stack.  Other reflogs are insert-only: there's no "pop the n'th master" command.

Restoring a stash

When you choose to apply a stash—with git stash apply or git stash pop; remember that the latter is just apply-then-drop—you tell Git which stash to use, using stash@{number} for instance.  This points directly to a w commit, but the w commit allows you to reach its i commit and, if it exists, its u commit.  The easy way to do that is to use the gitrevisions syntax for graph-walking.  For instance, to refer to commit i, which is the second parent of w, you can write:

```<code>stash^2
</code>```

because stash points to commit w and w's second parent is i.  If commit u exists in this stash, stash^3 will name it.

Hence, git stash apply first looks to see whether a u commit exists.  If so, git stash insists on restoring it.  Restoring a u commit requires that none of the files in u exist in the work-tree right now.

What this means is that if you have a bunch of untracked files, and you're not sure which ones are in u, you can just remove (or move-out-of-the-way) all untracked files.  That's by far the simplest thing to do.  If you want to be carefully selective, you will need to list out the names of the files that are in commit u, and there's no front-end user-facing command for that.  You can do it though, in multiple ways, as we'll see in a moment.

In any case, Git definitely has commits i and w.  (The git stash code makes sure there are two such commits, plus the optional third u commit, and rejects your command-line argument if not.)  So git stash apply needs to go about restoring i and w too.  The way it does this is:

Save the current index state.  This prevents applying a stash if you're in a conflicted merge that you have not concluded.

Unless you used --index, completely ignore commit i.  Otherwise, compare i vs w's first parent—the commit that was current at the time you saved the stash—using git diff.  Send the diff to git apply --cached.  Technically, the actual line of code in the old git-stash script is:

```<code>git diff-tree --binary $s^2^..$s^2 | git apply --cached
</code>```

($s is commit w so this uses i^ rather than w^ but i^ and w^ are the same; the diff uses diff-tree --binary so that it always works right, as plain diff won't diff binary files, and will use your per-user configuration, which is a bad idea here).

The apply step may fail.  If so, git stash apply --index fails and does nothing.  If the apply step succeeds, save the resulting index for later, then use git reset to reset it to match the HEAD commit.

There's also a fancy trick here: Git checks whether the saved index in step 1 matches the saved index in the stash.  If so, the index already has the right contents and there's no point in doing the git apply --cached.  This is not just an optimization; it's useful with git stash --keep-index: it makes git stash apply --index work for that case.  (Of course, you could run git stash apply without --index, if your index already matches the stash's i, but my guess is someone thought that was too unfriendly.)

Use the merge machinery to combine commit w with your current work-tree, using w's first parent as the merge base.  I won't go into details here, but this part can be quite messy.  If there are merge conflicts here, and the current work-tree did not match the HEAD commit when you started, it can be extremely difficult to get back to the state you were in.

(This is one of several reasons that I recommend avoiding git stash in general.  It is safe to use git stash in many cases, and if you really know what you're doing, you know how to make things safe for yourself in all cases.  But git stash is advertised as a quick and easy solution for Git newbies, and in fact, it's not at all quick, nor easy, in these corner cases!)

Your case (finally!)

In your case, you have run several git stash push --all operations, so you have several to many stashes—stash@{0} through stash@{9}, say, or maybe even more—some or all of which have u commits, which you can access via stash@{number}^3.

These u commits have no parent, so if you run:

```<code>git show stash@{1}^3
</code>```

for instance, Git will compare, i.e., git diff, the empty tree to the u commit for stash@{1}.  This will show the files (and the contents of the files—add --name-only to get just the names) in that u commit.

That could be what you want!  That shows you a list of which files are in the u commit for that stash.  That's not quite what you asked for, though:

... if there are files which exist in one of the stashes, but not locally

By "locally" here I assume you mean in your existing work-tree as it stands right now, without adding or removing any files to it.

If we run:

```<code>git diff <commit-specifier>
</code>```

with no additional options, Git will compare the contents of the specified commit to the contents of the work-tree.  The current index plays no role in this diff, though the contents of .gitignore do.  The files of interest are:

those in the given commit

those in the work-tree, whether or not they exist in the given commit, minus any files that (a) do exist in the work-tree and (b) are listed in .gitignore.

That is, suppose we name a commit—such as one of these u commits—that contains files a.ext, b.ext, and c.ext.  Your current work-tree either has an a.ext or does not; the same goes for b.ext and c.ext.  Your current work-tree also has d.ext and e.bin, neither of is in this u commit.

If file a.ext does not exist in your current work-tree, git diff will claim that, to convert commit u to match your work-tree, you should delete a.ext.  If file b.ext does exist in your work-tree and matches that in u, Git will say nothing about it.  If file c.ext does exist, but doesn't match the copy in u, Git will say that c.ext is modified, and to make c.ext in commit u make c.ext in your work-tree, particular lines need to be added and/or deleted: that's the diff instruction output.

Since d.ext does exist in your work-tree, git diff will say that to convert u to match your work-tree, you should add d.ext, with its current contents.  If *.bin is ignored, though, git diff won't tell you how to add it to commit u: the assumption here is that you don't want to make a new commit that's like u but has e.bin added, as e.bin is to be ignored.  That's true even if e.bin is in your index right now.  While git commit cares, this particular git diff doesn't.

Since commit u in each stash lists all (and only) the files saved in it, any instruction from Git that tells you that you must delete some file from u in order to make it match your work-tree, tells you that the file exists in u and not in your work-tree.  So we use --diff-filter=D to make git diff mention file a.ext.  This filter will exclude c.ext, as it does exist: it just has the wrong contents.  The set of files that git diff would report therefore consists solely of a.ext, which is in u but not in your work-tree.  The --name-only option makes git diff print just the file name, and not the actual instructions for converting the file.

There are still more ways to handle this problem, but these two—git show or git diff with --name-only and additional options if / as needed, plus a name for the stash's u commit—seem like the simplest.

Body:
TL;DR

You may want to use git diff --name-only --diff-filter=D stash@{number}^3 on each valid stash@{number}.  (To get a list of stashes, use git stash list.)

You may want to use git show --name-only stash@{number}^3 on each valid stash@{number}.  Note that this is git show stash@..., not git stash show.

To understand which and why, read on.

Long

What git stash does is a bit complicated, but it can be summarized pretty simply:

git stash push (or the old spelling, git stash save) makes two or three commits, with none of the commits it makes being on any branch.  Then it runs git reset or git clean or some combination of those, depending on flags used.

git stash apply merges some or all of the two or three commits in some stash with your existing index and work-tree.

git stash pop means run git stash apply, and then if that claims to succeed, run git stash drop.

Unfortunately, the above is actually pretty complex—it requires that you understand Git's usage of the index, for one thing–and yet is incomplete.  It says that git stash push makes two commits (or sometimes three), but it does not say what is in those commits, nor what form they have in your repository.  For the simplest usage of git stash, none of those matter too much, but for your case, they are crucial.

Commits

I'll just mention these briefly since, aside from the ones that git stash makes, we're not too concerned with them.  Each commit holds a complete snapshot of files.  Exactly which files, we'll see in a moment.  Along with the snapshot, the commit contains some metadata, including who made the commit, when (date-and-time-stamp), and why (log message).  Each commit has a unique hash ID, and as part of the metadata, each commit includes the hash ID of its parent—a link back to the previous commit.

A merge commit has links back to two or more parents.  Commits that are linked this way are normally closely related—which is why the linkage is parent/child, after all—but unlike the snapshot-plus-metadata part, there's no hard requirement that the files in any one commit relate much to those in any other.  We'll see that in a moment, with the stash commits, too.

Besides being identified by their hash IDs, commits are mostly permanent—though of course stash commits are intended to be non-permanent and will eventually go away after being dropped—and are completely read-only.  This means that they cannot be used to do any new work, which is why Git has more than just commits.  This is why you need a work-tree.

The index and the work-tree

As we just noted, the commits are read-only.  Not only that, the files stored in each commit are in a special, compressed, read-only format.  This means two or more commits can share a file that's the same in both commits, which in turn means that even if you commit some version of a file hundreds of times, Git only has to store it once.  I like to refer to these internal format files as freeze-dried.

In order for you to actually use or change your files, Git has to rehydrate them, turning them back into ordinary files that you can read and write.  The area in which commits are rehydrated for your use is your work-tree.  Git could stop here—with frozen commits holding dehydrated files, as permanent as the commits themselves, plus temporary, ephemeral, but useful work-tree files.  Other version control systems do stop here: you have, at any time, the freeze-dried copy of a file in the current commit, plus the useful one in the work-tree.  But for various reasons, Git adds a third copy of the file.  This extra copy sits between the commit and the work-tree, in what Git calls, variously, the index or the staging area.

The extra copy of each file that's in the index, between the frozen dehydrated copy in the current commit and the useful copy in the work-tree, is also in the dehydrated form.  The key difference between it and the current-commit copy is that it's not read-only.  You can overwrite it—though technically this just moves the previous one out of the way—with a new freeze-dried copy at any time.  That's what git add does: it freeze-dries the work-tree copy and uses that to overwrite the index copy.

This is why you have to git add files all the time.  They're already there, in the index, ready to commit—but they match the one that came out of the last commit.  You've modified the work-tree copy, but the frozen copy hasn't changed—of course not, it's frozen—and neither has the index copy, which matches the committed copy.  So now you have to re-compress the updated file and replace the index copy.  You run git add updated.ext and Git does just that.  Now your index and work-tree match, and differ from the frozen copy.

When you run git commit, Git looks not at your work-tree but at your index.  Whatever is in your index right then, Git packs those (already freeze-dried) files into a new commit, and that new commit becomes your current commit.  Now your index and commit match, because the new commit was made from the index.

This is also what determines whether a file is tracked.  If there is a copy in the index, the file is tracked.  The tracked copy—the one in the index—will be in the next commit, if you make it right now.  If you have a file in your work-tree that isn't in your index, that file is untracked.  That file won't be in the next commit, if you make it right now.  Hence the index is, in a way, the proposed next commit.  Every time you update it with git add, you're proposing to commit something slightly different.

Files that are untracked normally make various Git commands—especially git status—complain.  You can shut up these complaints, and also make git add --all not copy the files into the index, by listing some or all of these files in a .gitignore.  Note that listing a tracked file has no effect: it's already there in the index, so there's no question of ignoring it: it's not ignored.  Being listed in .gitignore only affects untracked files, and basically just makes it hard to accidentally track them, and shuts up git status about them.

You can put new files into the index at any time, using git add.  If the file wasn't there before, git add creates it in the index, rather than displacing the previous copy.  You can also remove files from the index at any time, using either git rm—this removes the file from the index and the work-tree—or git rm --cached, which removes the file from the index only.  At git commit time, it doesn't matter how a file is or isn't in the index, only whether it is or is not there, and if it is there, with what freeze-dried content.

It's worth a brief look at how git commit makes a new commit now.  When you run git commit, as we already mentioned, Git stuffs all the tracked files into a new commit.  First, though, Git gathers up the metadata: your name (from user.name), your email address (from user.email), the current date-and-time, and your log message.  Git also knows which commit is the current commit.  That commit's hash ID goes into the parent hash ID for the new commit.  And then Git saves the index and makes the commit, which automatically gets a new, unique hash ID.  As the last step of git commit, Git then writes the new commit's hash ID into the current branch name.

Hence if you used to have:

...--F--G--H   <-- master (HEAD)

with commit H as the current commit, and you've just made new commit I, new commit I points back to H, and Git has shoved the hash ID of I into the branch name master, so now you have:

...--F--G--H--I   <-- master

Now we can look at what git stash push does

When git stash builds a new stash without --all, it:

Writes out the index as a commit.  This is really easy since that's what git commit already does.  All Git has to do is not update the name master (and supply a log message for you, which it does).  Let's write out a commit i (lowercase) and not put it on master.  Instead, we'll remember it with a temporary variable:

...--F--G--H   <-- master
           |
           i   <-- $tempvar

Writes out the work-tree as a commit.  This is tricky to do efficiently, and also requires another special trick at the end.  Without going into the details of how git stash manages writing the work-tree, it's worth saying that this only writes tracked files.  The trick at the end is that git stash sets things up so that this new commit, which we'll call w, has two parents instead of one.  The first parent of w will be H and the second parent of w will be i:

...--F--G--H   <-- master
           |\
           i-w   <-- stash

With these two commits written out, Git updates the special name refs/stash to remember the hash ID of commit w.

This stash has no untracked files, regardless of whether they're ignored.  Commit i was made from the index, so it has no untracked files by definition.  The process that Git uses to make w only stores files that are in the index, so it has no untracked files either.

If you use git stash push --all, git stash push --include-untracked, or the git stash save flavors of these same commands, Git modifies the saving process a bit.  It makes commit i as usual, but then it makes a commit I call u, to hold the untracked files.  This extra commit either holds just the untracked files, excluding the untracked-and-ignored files, or it holds all the untracked files including the ignored ones.  This commit has no parent listed (which is a good trick, but easy to do when you use the Git plumbing commands, as git stash did before it was converted to C code recently); it just floats out there on its own:

...--F--G--H   <-- master
           |
           i   <-- $i_commit

           u   <-- $u_commit

Now git stash save goes back to its main path and makes commit w, but this time it gives w three parents: the current commit H, the index commit i, and the untracked-files commit u:

...--F--G--H   <-- master
           |\
           i-w   <-- stash
            /
           u

Quick recap: what's in i, w, and u

Commit i holds the index state.  There are, by definition, no untracked files in i.  Commit w holds the work-tree state, again without untracked files.  If commit u exists—it's optional, after all—it holds the untracked files, but no tracked files: the stash code parsimoniously saves those only in i and w.

Now git stash push cleans up

Having saved files in two or three commits, the last step of git stash push is to reset the index and work-tree.  If you told git stash to create commit u, it also removes from the work-tree any file it saved in commit u.

The reset of index and work-tree is normally done by a simple git reset --hard.  This leaves the index and work-tree in a state that matches the current commit H.  If you made the u commit, its files are now gone from the work-tree, otherwise those files are untouched in the work-tree.

However, git stash push (unlike git stash save) has the ability to reset less than the entire work-tree.  In that case, it's all done by a more complex bit of code.  You can also (well, instead) throw in the option --keep-index, in which case, instead of git reset --hard or similar, Git checks out what's in commit i, so that the work-tree matches i.  (It leaves the index itself alone, so i and the index continue to match.)  None of this affects your immediate task, but all of it affects the ability to restore one of these stashes.

Previous stashes get "stacked"

When git stash push is done, the new stash is the one identified by refs/stash, or just stash for short.  You can also describe this as stash@{0}, if you like.  Any existing stashes are moved up one, to stash@{1}, stash@{2}, and so on: what was stash@{1} becomes stash@{2}, etc.

The mechanism behind this is Git's reflogs, which apply to all references: branches have master@{1}, master@{2}, and so on, too.  The stash code just (ab?)uses these to implement the stash stack.  Other reflogs are insert-only: there's no "pop the n'th master" command.

Restoring a stash

When you choose to apply a stash—with git stash apply or git stash pop; remember that the latter is just apply-then-drop—you tell Git which stash to use, using stash@{number} for instance.  This points directly to a w commit, but the w commit allows you to reach its i commit and, if it exists, its u commit.  The easy way to do that is to use the gitrevisions syntax for graph-walking.  For instance, to refer to commit i, which is the second parent of w, you can write:

stash^2

because stash points to commit w and w's second parent is i.  If commit u exists in this stash, stash^3 will name it.

Hence, git stash apply first looks to see whether a u commit exists.  If so, git stash insists on restoring it.  Restoring a u commit requires that none of the files in u exist in the work-tree right now.

What this means is that if you have a bunch of untracked files, and you're not sure which ones are in u, you can just remove (or move-out-of-the-way) all untracked files.  That's by far the simplest thing to do.  If you want to be carefully selective, you will need to list out the names of the files that are in commit u, and there's no front-end user-facing command for that.  You can do it though, in multiple ways, as we'll see in a moment.

In any case, Git definitely has commits i and w.  (The git stash code makes sure there are two such commits, plus the optional third u commit, and rejects your command-line argument if not.)  So git stash apply needs to go about restoring i and w too.  The way it does this is:

Save the current index state.  This prevents applying a stash if you're in a conflicted merge that you have not concluded.

Unless you used --index, completely ignore commit i.  Otherwise, compare i vs w's first parent—the commit that was current at the time you saved the stash—using git diff.  Send the diff to git apply --cached.  Technically, the actual line of code in the old git-stash script is:

git diff-tree --binary $s^2^..$s^2 | git apply --cached

($s is commit w so this uses i^ rather than w^ but i^ and w^ are the same; the diff uses diff-tree --binary so that it always works right, as plain diff won't diff binary files, and will use your per-user configuration, which is a bad idea here).

The apply step may fail.  If so, git stash apply --index fails and does nothing.  If the apply step succeeds, save the resulting index for later, then use git reset to reset it to match the HEAD commit.

There's also a fancy trick here: Git checks whether the saved index in step 1 matches the saved index in the stash.  If so, the index already has the right contents and there's no point in doing the git apply --cached.  This is not just an optimization; it's useful with git stash --keep-index: it makes git stash apply --index work for that case.  (Of course, you could run git stash apply without --index, if your index already matches the stash's i, but my guess is someone thought that was too unfriendly.)

Use the merge machinery to combine commit w with your current work-tree, using w's first parent as the merge base.  I won't go into details here, but this part can be quite messy.  If there are merge conflicts here, and the current work-tree did not match the HEAD commit when you started, it can be extremely difficult to get back to the state you were in.

(This is one of several reasons that I recommend avoiding git stash in general.  It is safe to use git stash in many cases, and if you really know what you're doing, you know how to make things safe for yourself in all cases.  But git stash is advertised as a quick and easy solution for Git newbies, and in fact, it's not at all quick, nor easy, in these corner cases!)

Your case (finally!)

In your case, you have run several git stash push --all operations, so you have several to many stashes—stash@{0} through stash@{9}, say, or maybe even more—some or all of which have u commits, which you can access via stash@{number}^3.

These u commits have no parent, so if you run:

git show stash@{1}^3

for instance, Git will compare, i.e., git diff, the empty tree to the u commit for stash@{1}.  This will show the files (and the contents of the files—add --name-only to get just the names) in that u commit.

That could be what you want!  That shows you a list of which files are in the u commit for that stash.  That's not quite what you asked for, though:

... if there are files which exist in one of the stashes, but not locally

By "locally" here I assume you mean in your existing work-tree as it stands right now, without adding or removing any files to it.

If we run:

git diff <commit-specifier>

with no additional options, Git will compare the contents of the specified commit to the contents of the work-tree.  The current index plays no role in this diff, though the contents of .gitignore do.  The files of interest are:

those in the given commit

those in the work-tree, whether or not they exist in the given commit, minus any files that (a) do exist in the work-tree and (b) are listed in .gitignore.

That is, suppose we name a commit—such as one of these u commits—that contains files a.ext, b.ext, and c.ext.  Your current work-tree either has an a.ext or does not; the same goes for b.ext and c.ext.  Your current work-tree also has d.ext and e.bin, neither of is in this u commit.

If file a.ext does not exist in your current work-tree, git diff will claim that, to convert commit u to match your work-tree, you should delete a.ext.  If file b.ext does exist in your work-tree and matches that in u, Git will say nothing about it.  If file c.ext does exist, but doesn't match the copy in u, Git will say that c.ext is modified, and to make c.ext in commit u make c.ext in your work-tree, particular lines need to be added and/or deleted: that's the diff instruction output.

Since d.ext does exist in your work-tree, git diff will say that to convert u to match your work-tree, you should add d.ext, with its current contents.  If *.bin is ignored, though, git diff won't tell you how to add it to commit u: the assumption here is that you don't want to make a new commit that's like u but has e.bin added, as e.bin is to be ignored.  That's true even if e.bin is in your index right now.  While git commit cares, this particular git diff doesn't.

Since commit u in each stash lists all (and only) the files saved in it, any instruction from Git that tells you that you must delete some file from u in order to make it match your work-tree, tells you that the file exists in u and not in your work-tree.  So we use --diff-filter=D to make git diff mention file a.ext.  This filter will exclude c.ext, as it does exist: it just has the wrong contents.  The set of files that git diff would report therefore consists solely of a.ext, which is in u but not in your work-tree.  The --name-only option makes git diff print just the file name, and not the actual instructions for converting the file.

There are still more ways to handle this problem, but these two—git show or git diff with --name-only and additional options if / as needed, plus a name for the stash's u commit—seem like the simplest.


来源: stackexchange

问:
GParsExecutorsPool.withPool is not making Async connections
I am using groovy and Gpars to make async connection. I am getting a huge JSON as request to my API, i am splitting JSON using JSON Path.
$.${jsonobjstpath}..[i][j], Where i and j are values in range of 0:20, and looping over it. I am able to get correct splited json.
and these JSON batches i am sending to my API using GParsExecutorsPool.withPool. But gpar is waiting for the response.
Let say if processing API for one request is taking 10sec, gpar is waiting for 10 sec to send controller to loop. My code is below.

```<code>    import groovyx.gpars.GParsExecutorsPool;
    import groovyx.gpars.GParsPool;
    import jsr166y.ForkJoinPool;
    import jsr166y.RecursiveTask;

    def  invoke(mega) {
        def size=mega.get("size"); //get size of actual JSON objects
        def body=mega.get("content.body"); // Load JSON body
        int counter=Math.ceil(size/20); //Get Number of loops to run
        def Path="/AsyncInmp"; // Path to call function
        def Name="SplitJsonObject"; //Name of Function
        int i=0;
        int j=19;
        while(j<=size) {
            msg.put("i",i); //Send i value to function
            msg.put("j",j); // Send j value to function
            callPolicy(Path,Name,body); //Call function json path to get split json, receiving JSON with i and j values
            def split_body=resp.body;//response from split json
            def Path2="/AsyncInmp"; //path to connection function
            def Name2="connect"; //name of connection function
            GParsExecutorsPool.withPool {
              (0..<1).eachParallel { k ->
                callPolicy(Path2, Name2,split_body) //Call function to connect using gpars, This is not working
              }
            }
            j=j+20;
            i=i+20;
        }
        return true;
    }
</code>```

So how can i make async call using gpar as soon as my split json request is ready

how can i collect response from all async call

答:
You are calling withPool inside of your while loop and also using a range of size 1 in your eachParallel, I would guess these things combined essentially makes your code behave in a single threaded manner.

Changing it to something like this:

```<code>import java.util.concurrent.CopyOnWriteArrayList

def futures = [] as CopyOnWriteArrayList
GParsExecutorsPool.withPool {
  while(...) {
    ...
    futures << {
      callPolicy(Path2, Name2,split_body)
    }.async().call()
  }
}

// wait for all requests to complete
def results = futures*.get() // or futures.collect { it.get() } if this breaks

// results is now a list of return values from callPolicy
</code>```

I have not tested or run this code, but it should give you an idea of how you could move forward.

<-- edit after comments -->

A working example:

```<code>@Grab('org.codehaus.gpars:gpars:1.0.0')

import groovyx.gpars.*
import java.util.concurrent.*
import java.util.concurrent.atomic.*
import static groovyx.gpars.dataflow.Dataflow.task

random    = new Random()
sequence  = new AtomicInteger(-1)

def promises = [] as CopyOnWriteArrayList

GParsPool.withPool(25) { pool ->
  10.times { index ->
    promises << task {
      callPolicy(index)
    }
  }
}

def results = promises*.get()

results.each { map ->
  println map
}

def callPolicy(index) {
  Thread.sleep(random.nextInt(100) % 100)
  [index: index, sequence: sequence.incrementAndGet(), time: System.currentTimeMillis()]
}
</code>```

which produces the following type of output:

```<code>~> groovy solution.groovy
[index:0, sequence:9, time:1558893973348]
[index:1, sequence:1, time:1558893973305]
[index:2, sequence:8, time:1558893973337]
[index:3, sequence:5, time:1558893973322]
[index:4, sequence:7, time:1558893973337]
[index:5, sequence:4, time:1558893973320]
[index:6, sequence:3, time:1558893973308]
[index:7, sequence:6, time:1558893973332]
[index:8, sequence:0, time:1558893973282]
[index:9, sequence:2, time:1558893973308]

~>
</code>```

where we can see that the results are returned and also that the calls are made in a  multi-threaded manner since the sequence and the index values are not both in sequence.

ContentLicense: CC BY-SA 4.0

Body:
I am using groovy and Gpars to make async connection. I am getting a huge JSON as request to my API, i am splitting JSON using JSON Path.
$.${jsonobjstpath}..[i][j], Where i and j are values in range of 0:20, and looping over it. I am able to get correct splited json.
and these JSON batches i am sending to my API using GParsExecutorsPool.withPool. But gpar is waiting for the response.
Let say if processing API for one request is taking 10sec, gpar is waiting for 10 sec to send controller to loop. My code is below.

    import groovyx.gpars.GParsExecutorsPool;
    import groovyx.gpars.GParsPool;
    import jsr166y.ForkJoinPool;
    import jsr166y.RecursiveTask;

    def  invoke(mega) {
        def size=mega.get("size"); //get size of actual JSON objects
        def body=mega.get("content.body"); // Load JSON body
        int counter=Math.ceil(size/20); //Get Number of loops to run
        def Path="/AsyncInmp"; // Path to call function
        def Name="SplitJsonObject"; //Name of Function
        int i=0;
        int j=19;
        while(j<=size) {
            msg.put("i",i); //Send i value to function
            msg.put("j",j); // Send j value to function
            callPolicy(Path,Name,body); //Call function json path to get split json, receiving JSON with i and j values
            def split_body=resp.body;//response from split json
            def Path2="/AsyncInmp"; //path to connection function
            def Name2="connect"; //name of connection function
            GParsExecutorsPool.withPool {
              (0..<1).eachParallel { k ->
                callPolicy(Path2, Name2,split_body) //Call function to connect using gpars, This is not working
              }
            }
            j=j+20;
            i=i+20;
        }
        return true;
    }

So how can i make async call using gpar as soon as my split json request is ready

how can i collect response from all async call

Body:
You are calling withPool inside of your while loop and also using a range of size 1 in your eachParallel, I would guess these things combined essentially makes your code behave in a single threaded manner.

Changing it to something like this:

import java.util.concurrent.CopyOnWriteArrayList

def futures = [] as CopyOnWriteArrayList
GParsExecutorsPool.withPool {
  while(...) {
    ...
    futures << {
      callPolicy(Path2, Name2,split_body)
    }.async().call()
  }
}

// wait for all requests to complete
def results = futures*.get() // or futures.collect { it.get() } if this breaks

// results is now a list of return values from callPolicy

I have not tested or run this code, but it should give you an idea of how you could move forward.

<-- edit after comments -->

A working example:

@Grab('org.codehaus.gpars:gpars:1.0.0')

import groovyx.gpars.*
import java.util.concurrent.*
import java.util.concurrent.atomic.*
import static groovyx.gpars.dataflow.Dataflow.task

random    = new Random()
sequence  = new AtomicInteger(-1)

def promises = [] as CopyOnWriteArrayList

GParsPool.withPool(25) { pool ->
  10.times { index ->
    promises << task {
      callPolicy(index)
    }
  }
}

def results = promises*.get()

results.each { map ->
  println map
}

def callPolicy(index) {
  Thread.sleep(random.nextInt(100) % 100)
  [index: index, sequence: sequence.incrementAndGet(), time: System.currentTimeMillis()]
}

which produces the following type of output:

~> groovy solution.groovy
[index:0, sequence:9, time:1558893973348]
[index:1, sequence:1, time:1558893973305]
[index:2, sequence:8, time:1558893973337]
[index:3, sequence:5, time:1558893973322]
[index:4, sequence:7, time:1558893973337]
[index:5, sequence:4, time:1558893973320]
[index:6, sequence:3, time:1558893973308]
[index:7, sequence:6, time:1558893973332]
[index:8, sequence:0, time:1558893973282]
[index:9, sequence:2, time:1558893973308]

~>

where we can see that the results are returned and also that the calls are made in a  multi-threaded manner since the sequence and the index values are not both in sequence.


问:
Adding spaces to string based on list
I have a string s and a list of strings, arr.
The length of s is equal to the total length of strings in arr.
I need to split s into a list, such that each element in the list has the same length as the corresponding element in arr.

For example:

```<code>s = 'Pythonisanprogramminglanguage'

arr = ['lkjhgf', 'zx', 'qw', 'ertyuiopakk', 'foacdhlc']
</code>```

expected == ['Python', 'is', 'an', 'programming', 'language']
```

答:
Yet another approach would be to create a regex pattern describing the desired length of words. You can replace every character by . (=any character) and surround the words with ():

```<code>arr = ['lkjhgf', 'zx', 'q', 'ertyuiopakk', 'foacdhlc']

import re

pattern = '(' + ')('.join(re.sub('.', '.', word) for word in arr) + ')'
#=> '(......)(..)(.)(...........)(........)'
</code>```

If the pattern matches, you get the desired words in groups directly:

```<code>s = 'Pythonisaprogramminglanguage'
re.match(pattern, s).groups()
#=> ('Python', 'is', 'a', 'programming', 'language')
</code>```

Title: Adding spaces to string based on list

Body:
I have a string s and a list of strings, arr.
The length of s is equal to the total length of strings in arr.
I need to split s into a list, such that each element in the list has the same length as the corresponding element in arr.

For example:

s = 'Pythonisanprogramminglanguage'

arr = ['lkjhgf', 'zx', 'qw', 'ertyuiopakk', 'foacdhlc']

expected == ['Python', 'is', 'an', 'programming', 'language']

Body:
Yet another approach would be to create a regex pattern describing the desired length of words. You can replace every character by . (=any character) and surround the words with ():

arr = ['lkjhgf', 'zx', 'q', 'ertyuiopakk', 'foacdhlc']

import re

pattern = '(' + ')('.join(re.sub('.', '.', word) for word in arr) + ')'
#=> '(......)(..)(.)(...........)(........)'

If the pattern matches, you get the desired words in groups directly:

s = 'Pythonisaprogramminglanguage'
re.match(pattern, s).groups()
#=> ('Python', 'is', 'a', 'programming', 'language')


问:
Why does this generate two different Bezier curves despite having the same anchors/handles (manim)?
I am trying to have two identical Bezier curves in the same scene, one with an end tip and the other with a start tip, but the Bezier curves come out differently despite having the same anchors and handles. I know I can add both tips to the same Bezier curve but to integrate the graphics into my existing code (to animate it) I need to have them separate. Sample code to demonstrate the problem is as follows:

from manimlib.imports import *
class Testing3(Scene):
    def construct(self):
        coords_list=[0.818*UP+.9*UP, -2*RIGHT+((1/6-19/36)*np.sqrt(3))*UP+.9*UP]
        node_list=[]
        for i in range(2):
            mobject = VMobject()
            number = TexMobject(str(i+1))
            circle = Circle(radius=0.4,color=WHITE)
            mobject.add(number)
            mobject.add(circle)
            mobject.move_to(coords_list[i])
            node_list.append(mobject)

        arc1=TipableVMobject()
        arc1.add_cubic_bezier_curve(
            node_list[1].get_center(),
            node_list[1].get_center()-3*RIGHT+2*UP,
            node_list[1].get_center()-2*RIGHT+5.2*UP,
            node_list[0].get_center()
        )
        arc1.pointwise_become_partial(
            arc1,
            0.4/arc1.get_arc_length(n_sample_points=20),
            1-0.2/arc1.get_arc_length(n_sample_points=100)
        )
        arc1.add_tip(tip_length=0.2)

        arc2=TipableVMobject()
        arc2.add_cubic_bezier_curve(
            node_list[1].get_center(),
            node_list[1].get_center()-3*RIGHT+2*UP,
            node_list[1].get_center()-2*RIGHT+5.2*UP,
            node_list[0].get_center()
        )
        arc2.pointwise_become_partial(
            arc2,
            0.4/arc2.get_arc_length(n_sample_points=20),
            1-0.2/arc2.get_arc_length(n_sample_points=100)
        )
        arc2.add_tip(tip_length=0.2,at_start=True)
        self.add(*node_list,arc1,arc2)
        self.wait()
```

I have tried making a copy of the Bezier curve but it produces the same result.

答:
For the moment this is only can I do:

class Testing3(Scene):
    def construct(self):
        coords_list=[0.818*UP+.9*UP, -2*RIGHT+((1/6-19/36)*np.sqrt(3))*UP+.9*UP]
        node_list=[]
        for i in range(2):
            mobject = VMobject()
            number = TexMobject(str(i+1))
            circle = Circle(radius=0.4,color=WHITE)
            mobject.add(number)
            mobject.add(circle)
            mobject.move_to(coords_list[i])
            node_list.append(mobject)

        arc1=TipableVMobject()
        arc1.add_cubic_bezier_curve(
        node_list[1].get_center(),
        node_list[1].get_center()-3*RIGHT+2*UP,
        node_list[1].get_center()-2*RIGHT+5.2*UP,
        node_list[0].get_center()
        )
        arc1.pointwise_become_partial(
        arc1,
        0.4/arc1.get_arc_length(n_sample_points=20),
        1-0.2/arc1.get_arc_length(n_sample_points=100)
        )
        arc1.add_tip(tip_length=0.2,
        #at_start=True
        )
        arc1.add_tip(tip_length=0.2,
        at_start=True
        )
        arc1.set_color(RED)

        arc2=TipableVMobject()
        arc2.add_cubic_bezier_curve(
        node_list[1].get_center(),
        node_list[1].get_center()-3*RIGHT+2*UP,
        node_list[1].get_center()-2*RIGHT+5.2*UP,
        node_list[0].get_center()
        )
        arc2.pointwise_become_partial(
        arc2,
        0.4/arc2.get_arc_length(n_sample_points=20),
        1-0.2/arc2.get_arc_length(n_sample_points=100)
        )
        arc2.add_tip(tip_length=0.2,
        #at_start=True
        )
        arc2.add_tip(tip_length=0.2,
        at_start=True
        )
        arc2.set_color(BLUE)

        arc1.remove(arc1[-2])
        arc2.remove(arc2[-1])

        self.add(*node_list,arc1)

        self.wait()
        self.add(arc2)
        self.wait()

```

Body:
I am trying to have two identical Bezier curves in the same scene, one with an end tip and the other with a start tip, but the Bezier curves come out differently despite having the same anchors and handles. I know I can add both tips to the same Bezier curve but to integrate the graphics into my existing code (to animate it) I need to have them separate. Sample code to demonstrate the problem is as follows:

from manimlib.imports import *
class Testing3(Scene):
    def construct(self):
        coords_list=[0.818*UP+.9*UP, -2*RIGHT+((1/6-19/36)*np.sqrt(3))*UP+.9*UP]
        node_list=[]
        for i in range(2):
            mobject = VMobject()
            number = TexMobject(str(i+1))
            circle = Circle(radius=0.4,color=WHITE)
            mobject.add(number)
            mobject.add(circle)
            mobject.move_to(coords_list[i])
            node_list.append(mobject)

        arc1=TipableVMobject()
        arc1.add_cubic_bezier_curve(
            node_list[1].get_center(),
            node_list[1].get_center()-3*RIGHT+2*UP,
            node_list[1].get_center()-2*RIGHT+5.2*UP,
            node_list[0].get_center()
        )
        arc1.pointwise_become_partial(
            arc1,
            0.4/arc1.get_arc_length(n_sample_points=20),
            1-0.2/arc1.get_arc_length(n_sample_points=100)
        )
        arc1.add_tip(tip_length=0.2)

        arc2=TipableVMobject()
        arc2.add_cubic_bezier_curve(
            node_list[1].get_center(),
            node_list[1].get_center()-3*RIGHT+2*UP,
            node_list[1].get_center()-2*RIGHT+5.2*UP,
            node_list[0].get_center()
        )
        arc2.pointwise_become_partial(
            arc2,
            0.4/arc2.get_arc_length(n_sample_points=20),
            1-0.2/arc2.get_arc_length(n_sample_points=100)
        )
        arc2.add_tip(tip_length=0.2,at_start=True)
        self.add(*node_list,arc1,arc2)
        self.wait()

I have tried making a copy of the Bezier curve but it produces the same result.


问:
Using a For Loop to change an If statement
Just a real quick one. I has a list of variables which only change by 1 digit. I want my if statement to refer to each individual variable, but I'm not sure how to go about it. Can you help me out?

```<code>CheckGabba1 = IntVar()
CheckGabba2 = IntVar()
CheckGabba3 = IntVar()
## etc. (x10)

## There are items in these lists (This is just to show that they are lists)
AllEventsGabba = []
SelectedEventsGabba = []

NumEvents = 10
ListIndex = 0

for EventCheck in range(NumEvents):
   if (CheckGabba(ListIndex + 1)).get() == 1:
      SelectedEventsGabba.append(AllEventsGabba[ListIndex])
      ListIndex += 1
   else:
      ListIndex += 1
</code>```

Obviously (CheckGabba(ListIndex + 1) is wrong, but I'm not sure what it needs to be replaced with to get the loop to autonomously check each variable, rather than hard-writing (Which I can do, but would prefer not to).

答:
You could group all CheckGabbas in a List and loop over them, like

```<code>check_list=[CheckGabba1,CheckGabba2,CheckGabba3]
for check in check_list:
    if check.get()==1:
</code>```

an alternative would be to use exec on the string, like

```<code>exec "CheckGabba("+str(Listindex+1)+")"
</code>```

Body:
Just a real quick one. I has a list of variables which only change by 1 digit. I want my if statement to refer to each individual variable, but I'm not sure how to go about it. Can you help me out?

CheckGabba1 = IntVar()
CheckGabba2 = IntVar()
CheckGabba3 = IntVar()
## etc. (x10)

## There are items in these lists (This is just to show that they are lists)
AllEventsGabba = []
SelectedEventsGabba = []

NumEvents = 10
ListIndex = 0

for EventCheck in range(NumEvents):
   if (CheckGabba(ListIndex + 1)).get() == 1:
      SelectedEventsGabba.append(AllEventsGabba[ListIndex])
      ListIndex += 1
   else:
      ListIndex += 1

Obviously (CheckGabba(ListIndex + 1) is wrong, but I'm not sure what it needs to be replaced with to get the loop to autonomously check each variable, rather than hard-writing (Which I can do, but would prefer not to).

Body:
You could group all CheckGabbas in a List and loop over them, like

check_list=[CheckGabba1,CheckGabba2,CheckGabba3]
for check in check_list:
    if check.get()==1:

an alternative would be to use exec on the string, like

exec "CheckGabba("+str(Listindex+1)+")"


问:
Laravel Eloquent - Conditional Data Fetching
I've a customer and customer group table. I want to search the customers based on term/filter text.

Say, there is two customer_group_id, 7 and 8. When 8, I'll need to find mobile fields in orWhere clause, otherwise not.

What I've tried is

```<code>$contacts = Contact::where(function ($query) use ($term) {
    $query->where('contacts.name', 'like', '%' . $term .'%')
});

// For customer_group_id=8
$contacts->when('customer_group_id=8', function($q) use ($term){
    return $q->orWhere('mobile', 'like', '%' . $term .'%');
});
</code>```

The when() is not working. It showing all the results. I know that I've to pass any boolean value in the when() functions first parameter.

Is there any solution for this problem? Or what is the other way I can get the data's.

答:
The when() method doesn't add an if statement to your query, it is just a way to save you from writing an if statement in your code.

To achieve what you're after you can use nested orWhere() clause:

```<code>$contacts = Contact::where('name', 'like', '%' . $term . '%')
    ->orWhere(function ($query) use($term) {
        $query->where('customer_group_id', 8)->where('name', 'like', '%' . $term . '%');
    })
    ->get();
</code>```

If there is more to your query than what you've put in your question then you can simply wrap the above in another where clause:

```<code>$contacts = Contact::where(function ($query) use ($term) {
    $query->where('name', 'like', '%' . $term . '%')
        ->orWhere(function ($query) use ($term) {
            $query->where('customer_group_id', 8)->where('name', 'like', '%' . $term . '%');
        });
})
    ->where('some column', 'some value')
    ->get();
</code>```

Body:
I've a customer and customer group table. I want to search the customers based on term/filter text.

Say, there is two customer_group_id, 7 and 8. When 8, I'll need to find mobile fields in orWhere clause, otherwise not.

What I've tried is

$contacts = Contact::where(function ($query) use ($term) {
    $query->where('contacts.name', 'like', '%' . $term .'%')
});

// For customer_group_id=8
$contacts->when('customer_group_id=8', function($q) use ($term){
    return $q->orWhere('mobile', 'like', '%' . $term .'%');
});

The when() is not working. It showing all the results. I know that I've to pass any boolean value in the when() functions first parameter.

Is there any solution for this problem? Or what is the other way I can get the data's.

Body:
The when() method doesn't add an if statement to your query, it is just a way to save you from writing an if statement in your code.

To achieve what you're after you can use nested orWhere() clause:

$contacts = Contact::where('name', 'like', '%' . $term . '%')
    ->orWhere(function ($query) use($term) {
        $query->where('customer_group_id', 8)->where('name', 'like', '%' . $term . '%');
    })
    ->get();

If there is more to your query than what you've put in your question then you can simply wrap the above in another where clause:

$contacts = Contact::where(function ($query) use ($term) {
    $query->where('name', 'like', '%' . $term . '%')
        ->orWhere(function ($query) use ($term) {
            $query->where('customer_group_id', 8)->where('name', 'like', '%' . $term . '%');
        });
})
    ->where('some column', 'some value')
    ->get();


问:
How to access previous value of a field in django model form before save?
I need to access the previous value of the Django model instance field before saving the form. For example in the form_valid method need to access previous values of the model instance. How can I achieve this?

答:
Imagine that you have MyModel table. Now let's create instance of MyModel, and return one instance (row).

```<code>mymodel_instance = MyModel.objects.get(pk=14) # This returns instance of MyModel.
# Now lets get all values, before mymode_instance.
mymodel_qs = MyModel.objects.filter(pk__lt=mymodel_instance.pk) # This returns QuerySet (All values before mymodel_instance).
# iterate over all previous values.
for mymodel_obj in mymodel_qs:
    print(mymodel_obj, mymodel_obj.pk) # This will print all previous instance and id.
</code>```

I hope, it will help you.

Body:
Imagine that you have MyModel table. Now let's create instance of MyModel, and return one instance (row).

mymodel_instance = MyModel.objects.get(pk=14) # This returns instance of MyModel.
# Now lets get all values, before mymode_instance.
mymodel_qs = MyModel.objects.filter(pk__lt=mymodel_instance.pk) # This returns QuerySet (All values before mymodel_instance).
# iterate over all previous values.
for mymodel_obj in mymodel_qs:
    print(mymodel_obj, mymodel_obj.pk) # This will print all previous instance and id.

I hope, it will help you.


问:
How do I chain multiple jquery fancyboxes?
I'm using fancybox for modals in my web application.

There are cases when I'd like to popup a 2nd fancybox while one is already opened.  Does anyone know of a way to do this?  I'm ok with one opening after the other closes, or both being open at the same time one underneath the other.

Again, i'm using jquery and fancybox in my application.

答:
I've just tackled this problem myself.

Scenario:

Launching one fancybox using an iframe

From the opened fancybox, open another fancybox with content delivered by an ajax webservice.

Key points

If using fancybox and iframes, you need to use parent.$.fancybox, otherwise $.fancybox will do.

Don't forget to show activity before loading content

Don't forget to resize after loading the content

Code snippet:

```<code>        if (parent) {
        // if in an iframe we need to show activity for the parents' fancybox
        parent.$.fancybox.showActivity();
    }
    else {
        // otherwise show activity for the fancybox of the current window
        $.fancybox.showActivity();
    }

            // I'm using Ajax to fetch the content but you can fetch it in other ways too
    $.ajax({
        url: "your url goes here",
        type: "POST",
        contenttype: "text/xml; charset=utf-8",
        dataType: "xml",
        data: { "name": "john"},
        success: function (data, textStatus, jqXHR) {

            if (parent) {
                // if in an iframe we need to push the content into the parents' fancybox
                parent.$.fancybox($(jqXHR.responseXML).text());
                parent.$.fancybox.resize();
            }
            else {
                // otherwise push the content into the fancybox of the current window
                $.fancybox($(jqXHR.responseXML).text());
                $.fancybox.resize();
            }

        }
    });
</code>```

ContentLicense: CC BY-SA 2.5

Body:
I've just tackled this problem myself.

Scenario:

Launching one fancybox using an iframe

From the opened fancybox, open another fancybox with content delivered by an ajax webservice.

Key points

If using fancybox and iframes, you need to use parent.$.fancybox, otherwise $.fancybox will do.

Don't forget to show activity before loading content

Don't forget to resize after loading the content

Code snippet:

        if (parent) {
        // if in an iframe we need to show activity for the parents' fancybox
        parent.$.fancybox.showActivity();
    }
    else {
        // otherwise show activity for the fancybox of the current window
        $.fancybox.showActivity();
    }

            // I'm using Ajax to fetch the content but you can fetch it in other ways too
    $.ajax({
        url: "your url goes here",
        type: "POST",
        contenttype: "text/xml; charset=utf-8",
        dataType: "xml",
        data: { "name": "john"},
        success: function (data, textStatus, jqXHR) {

            if (parent) {
                // if in an iframe we need to push the content into the parents' fancybox
                parent.$.fancybox($(jqXHR.responseXML).text());
                parent.$.fancybox.resize();
            }
            else {
                // otherwise push the content into the fancybox of the current window
                $.fancybox($(jqXHR.responseXML).text());
                $.fancybox.resize();
            }

        }
    });

ContentLicense: CC BY-SA 3.0


问:
How to avoid a thread being completed in C#?
I have a RabbitMQ client program written in C#. While the application works in console based application (because execution is blocked by Console.ReadLine) it does not work in Windows Form based application. In Windows Form application, execution doesn't wait on Console.ReadLine and terminates on completion. I am looking for solution where my listener keeps monitoring for new messages from server without being terminated.
Here is the the client code :</p>

```<code>    try {
            var factory = new ConnectionFactory() { HostName = "xxx" , UserName ="xxx", Password="xxx"};
            using(var connection = factory.CreateConnection())
            using(var channel = connection.CreateModel())
            {
                channel.ExchangeDeclare(exchange: "call_notify", type: "fanout");

                var queueName = channel.QueueDeclare().QueueName;
                channel.QueueBind(queue: queueName,
                                  exchange: "call_notify",
                                  routingKey: "");

                var consumer = new EventingBasicConsumer(channel);
                consumer.Received += (model, ea) =>
                {
                    var body = ea.Body;
                    var message = Encoding.UTF8.GetString(body);
                    Console.WriteLine(message);
                };
                channel.BasicConsume(queue: queueName,
                                     autoAck: true,
                                     consumer: consumer);

                Console.WriteLine(" Press [enter] to exit.");
                Console.ReadLine();  // Program does'nt wait here in windows form based application
            }
        }
</code>```

答:
Thanks everyone! With all your suggestions i have found multiple ways to accomplish this.

The way i implemented this is by making Factory, Connection and Channel as class variables and have defined them in MainForm constructor. This way objects are preserved and program keeps listening for incoming messages.

Body:
I have a RabbitMQ client program written in C#. While the application works in console based application (because execution is blocked by Console.ReadLine) it does not work in Windows Form based application. In Windows Form application, execution doesn't wait on Console.ReadLine and terminates on completion. I am looking for solution where my listener keeps monitoring for new messages from server without being terminated.
Here is the the client code :

    try {
            var factory = new ConnectionFactory() { HostName = "xxx" , UserName ="xxx", Password="xxx"};
            using(var connection = factory.CreateConnection())
            using(var channel = connection.CreateModel())
            {
                channel.ExchangeDeclare(exchange: "call_notify", type: "fanout");

                var queueName = channel.QueueDeclare().QueueName;
                channel.QueueBind(queue: queueName,
                                  exchange: "call_notify",
                                  routingKey: "");

                var consumer = new EventingBasicConsumer(channel);
                consumer.Received += (model, ea) =>
                {
                    var body = ea.Body;
                    var message = Encoding.UTF8.GetString(body);
                    Console.WriteLine(message);
                };
                channel.BasicConsume(queue: queueName,
                                     autoAck: true,
                                     consumer: consumer);

                Console.WriteLine(" Press [enter] to exit.");
                Console.ReadLine();  // Program does'nt wait here in windows form based application
            }
        }


问:
How to get a message from Telegram groups by API?
I was looking for some way to listen and catch new messages provided by telegram groups.

I have not found libraries or API in order to do this in Python.

Someone having any suggestion?

答:
There are two ways to achieve your goal:

Method 1:

My suggested library for python: python-telegram-bot

Create a bot.

Add the bot to the desired group as administrator.

Listen to messages as you normally listen in bots.

Method 2:

My suggested library for python: Telethon

Join the desired group as a user (not a bot).

Create a simple client that listens to new messages.


问:
VBA Code Scraper not placing data in right columns
The code works fine, but I need it to extract ONLY emails and URLs and place the email in Sheet1 "Scraper" NEXT BLANK ROW

```<code>Emails =  Column A
Urls =  Column B
</code>```

Currently it extracts anything text, emails or URL and places them in column A or B.

I only need Emails or URLs. I have been stuck on this for sometime and can't seem to work it out

Also I am not sure if my DELETE DUPLICATES is deleting duplicate rows or duplicates in column. It SHOULD be duplicate rows.

How the code works:

On Sheet2 "URL List" I have a list of URLs, the code runs through this and places the results onto Sheet1 "Scraper". and deletes any duplicates

It is only supposed to scraper email and URLs and place them in Column A,B on NEXT BLANK ROW.

I have tried to fix the problem but it is out of my scope.

```<code>Private Sub fbStart_Click()
'Set sheet2 URL List and open Internet Explorer
    Dim lr          As Long
    Dim x           As Long
    Dim arr()       As Variant
    Dim wks         As Worksheet
    Dim ie          As Object
    Dim dd(1 To 2)  As String
    Dim Fr          As Long

    On Error Resume Next
    Application.ScreenUpdating = False

    Set wks = ThisWorkbook.Sheets("Url List")
    With wks
        Fr = .Cells(.Rows.Count, 6).End(xlUp).Offset(1).Row
        lr = .Cells(.Rows.Count, 1).End(xlUp).Row
        .Cells(1, 5).Value = lr
        arr = .Range(.Cells(Fr, 1), .Cells(lr, 1)).Value
    End With

    'Show Internet Explorer and add delay in seconds if needed
    Set ie = CreateObject("InternetExplorer.Application")
    With ie
        .Visible = True
        Application.Wait Now + TimeValue("0:00:0")

        For x = LBound(arr, 1) To UBound(arr, 1)
            .navigate arr(x, 1)
            wtime = Time
            Do While .Busy Or .readyState <> 4
                DoEvents

            'Skip pages with Captchas  + write the word Captcha in Sheet 2 Column C
                If Time > (wtime + TimeValue("00:00:10")) Then
                    Cells(x + 1, "C").Value = "Captcha"
                    Exit Do
                End If
            Loop

            On Error Resume Next
            'Variable for document or data which need to be extracted out of webpage, change innertext number if same class used
            Dim doc As HTMLDocument
            Set doc = ie.document
            dd(1) = doc.getElementsByClassName("_50f4")(2).innerText
            dd(2) = doc.getElementsByClassName("_50f4")(3).innerText

            'Paste the web data into Sheet1 "Scraper" in next BLANK ROW
            With Sheet1
                .Cells(.Rows.Count, "A").End(xlUp).Offset(1, 0).Resize(, 2).Value = dd
            End With

            ' Put A number 1 in Sheet2 "Url List"column B to notify this URL is done
            Sheets("Url List").Range("B" & Rows.Count).End(xlUp).Offset(1, 0).Value = 1

             'Deletes duplicates in column A Sheet1
            Columns(1).RemoveDuplicates Columns:=Array(1)
            Columns(2).RemoveDuplicates Columns:=Array(1)

             'Count No1 in sheet2 Column B
            With Worksheets("Url List")
                Lastrow = .Cells(.Rows.Count, "B").End(xlUp).Row
                Sheets("Url List").Range("B1").Value = Lastrow
            End With
            Call Autoclick_Click
        Next x
       .Quit
    End With

    'Hide FaceBook Scraper Form
    ScraperForm.Hide

End Sub
</code>```

答:
Below is to show you how to handle finding email and website address. You already have your loop and de-duplicate. Below are helper methods for extracting the required info. You can simply assign from the variables email and website to your cells in loop. I show a method using a helper function to determine lastRow in target sheet and writing out variables to correct columns in one go.

I can help with implementing the loop integration if needed, but the emphasis here was on explaining what could be done for identifying those elements of interest and how to write out to correct columns. Tbh - de-duplicating is so easily done in sheet at end but you can also use macro recorder to get perfectly functional code for that single step/use existing SO answers.

tl;dr;

This would be a lot easier if  :contains / :has css pseudo classes were permitted. Instead, my approach is as follows:

email - find the href attribute whose value starts with mailto

website - check that there is a website icon on the page

Specify a parent of both the website icon and the website address

Loop all matches to that parent specification checking if contains the website icon (this is where pseudo class selectors would have simplified things). If match found then we have the shared parent of both icon and hopefully website address; use childOfSiblingCssSelector (we are looking at a child of the following div in this case) css selector to extract the website url.

Notes:

The entire thing is kept quite high level/generic such that you can adjust your css selectors to hopefully cater for different scenarios. Consequence - may seem a little verbose.

Helper functions are provided to handle element matching. Name these in a way that makes sense for what they are doing. I think some room for improvement here.

Whilst technically the second helper, GetText, could be used to extract the email address (I'd probably add another argument to function call to specify attribute to extract) as well as website address, it seems far quicker, currently, to simply target the appropriate href as detailed above.

I have kept the css selectors as local variables close to their usage; you could have them as constants, closer to top of module, where easier to access perhaps? Unsure without seeing how this performs over time/different urls

Css selectors are chosen over .getElementsBy methods for two reasons: 1) there is browser optimization for css selectors so, if well formulated, css will be faster 2) I want to preserve the flexibility of the code/helper functions - you have far more specificity with css selectors in terms of what patterns you can express. I deemed this important as I don't know what future cases you may need to handle.

I am deliberately not using class name and index e.g. doc.getElementsByClassName("_50f4")(2).innerText, as I am unfamiliar with the range of potential use cases; this feels a little fragile as relies on consistent ordering and numbering of elements (at least up to these indices).

TODO:

Rather than instantiate a new HTMLDocument each time in GetText, it is more efficient to pass another  HTMLDocument argument in the function signature i.e. from calling procedure. A re-factor could take that into consideration.

This type of coding might lend itself to being class based in the future. Particularly if error handling is to be added and further functions.

VBA:

```<code>Option Explicit
'VBE > Tools > References > HTML Object Library
Public Sub test()
    Dim ie As Object, ws As Worksheet
    Set ie = CreateObject("InternetExplorer.Application")
    Set ws = ThisWorkbook.Worksheets("Scraper")

    With ie
        .Visible = True
        .Navigate2 "https://www.facebook.com/pg/SalemFordNH/about/?ref=page_internal%5Blink%5D"

        While .Busy Or .readyState < 4: DoEvents: Wend

        With .document

            Dim email As String, website As String, iconCssSelector As String
            'iconCssSelector for website icon in this instance
            iconCssSelector = "[src='https://static.xx.fbcdn.net/rsrc.php/v3/yV/r/EaDvTjOwxIV.png']"

            If ElementIsPresent(ie.document, "[href^=mailto]") Then
                email = ie.document.querySelector("[href^=mailto]").innerText
            Else
                email = "Not found"
            End If

            Dim parents As Object, sharedParentCssSelector As String, childOfSiblingCssSelector As String
            sharedParentCssSelector = "._5aj7" 'target parent of both icon and the website link
            childOfSiblingCssSelector = "._50f4" '< to target website address after finding right parent

            If ElementIsPresent(ie.document, iconCssSelector) _
                And ElementIsPresent(ie.document, sharedParentCssSelector) Then

                Set parents = ie.document.querySelectorAll(sharedParentCssSelector) 'css selector used to allow for greater flexibility in element matching
                website = GetText(ie.document, parents, iconCssSelector, childOfSiblingCssSelector)
            Else
                website = "Not found"
            End If
        End With
        'Assumes headers already present
        Dim nextRow As Long
        nextRow = GetLastRow(ws, 1) + 1
        ws.Cells(nextRow, 1).Resize(1, 2) = Array(email, website)
        .Quit
    End With
End Sub

Public Function ElementIsPresent(ByVal document As HTMLDocument, ByVal cssSelector As String) As Boolean
    ElementIsPresent = document.querySelectorAll(cssSelector).length > 0
End Function

Public Function GetText(ByVal document As HTMLDocument, ByVal parents As Object, ByVal iconCssSelector As String, ByVal childOfSiblingCssSelector As String) As String
    'in this instance and with microsoft IE DOM you cannot select for parent of an element with pseudo class _
    of :has(>child); nor use :contains... instead pass expected parent selector, that houses _
    both the icon element for website and the website address itself, and loop all matches checking for website icon _
    if found use childOfSiblingCssSelector to extract
    Dim i As Long, html As HTMLDocument
    Set html = New HTMLDocument

    For i = 0 To parents.length - 1
        html.body.innerHTML = parents.item(i).innerHTML
        If ElementIsPresent(html, iconCssSelector) Then
            GetText = html.querySelector(childOfSiblingCssSelector).innerText
            Exit Function
        End If
    Next
    GetText = "Not found"
End Function

Public Function GetLastRow(ByVal ws As Worksheet, Optional ByVal columnNumber As Long = 1) As Long
    With ws
        GetLastRow = .Cells(.rows.Count, columnNumber).End(xlUp).Row
    End With
End Function
</code>```

Project references (VBE > Tools > References):

Microsoft HTML Object Library

Additional reading:

https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Selectors

https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelectorAll

https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelector

Edit:

Example of loop - assumes no empty rows in column A between urls.

```<code>Option Explicit
'VBE > Tools > References > HTML Object Library
Public Sub test()
    Dim ie As Object, ws As Worksheet, wsUrls As Worksheet, urls()
    Set ie = CreateObject("InternetExplorer.Application")
    Set ws = ThisWorkbook.Worksheets("Scraper")
    Set wsUrls = ThisWorkbook.Worksheets("Url List")

    With wsUrls
        urls = Application.Transpose(.Range("A2:A" & .Cells(.rows.Count, "A").End(xlUp).Row).Value)
    End With
    Dim results(), r As Long
    ReDim results(1 To UBound(urls), 1 To 2)

    With ie
        .Visible = True

        For r = LBound(urls) To UBound(urls)
            .Navigate2 urls(r)

            While .Busy Or .readyState < 4: DoEvents: Wend

            With .document

                Dim email As String, website As String, iconCssSelector As String
                'iconCssSelector for website icon in this instance
                iconCssSelector = "[src='https://static.xx.fbcdn.net/rsrc.php/v3/yV/r/EaDvTjOwxIV.png']"

                If ElementIsPresent(ie.document, "[href^=mailto]") Then
                    email = ie.document.querySelector("[href^=mailto]").innerText
                Else
                    email = "Not found"
                End If

                Dim parents As Object, sharedParentCssSelector As String, childOfSiblingCssSelector As String
                sharedParentCssSelector = "._5aj7" 'target parent of both icon and the website link
                childOfSiblingCssSelector = "._50f4" '< to target website address after finding right parent

                If ElementIsPresent(ie.document, iconCssSelector) _
        And ElementIsPresent(ie.document, sharedParentCssSelector) Then

                    Set parents = ie.document.querySelectorAll(sharedParentCssSelector) 'css selector used to allow for greater flexibility in element matching
                    website = GetText(ie.document, parents, iconCssSelector, childOfSiblingCssSelector)
                Else
                    website = "Not found"
                End If
            End With
            'Assumes headers already present
            Dim nextRow As Long
            results(r, 1) = email
            results(r, 2) = website
        Next
        .Quit
    End With
    nextRow = GetLastRow(ws, 1) + 1
    ws.Cells(nextRow, 1).Resize(UBound(results, 1), UBound(results, 2)) = results
End Sub

Public Function ElementIsPresent(ByVal document As HTMLDocument, ByVal cssSelector As String) As Boolean
    ElementIsPresent = document.querySelectorAll(cssSelector).length > 0
End Function

Public Function GetText(ByVal document As HTMLDocument, ByVal parents As Object, ByVal iconCssSelector As String, ByVal childOfSiblingCssSelector As String) As String
    'in this instance and with microsoft IE DOM you cannot select for parent of an element with pseudo class _
    of :has(>child); nor use :contains... instead pass expected parent selector, that houses _
    both the icon element for website and the website address itself, and loop all matches checking for website icon _
    if found use childOfSiblingCssSelector to extract
    Dim i As Long, html As HTMLDocument
    Set html = New HTMLDocument

    For i = 0 To parents.length - 1
        html.body.innerHTML = parents.item(i).innerHTML
        If ElementIsPresent(html, iconCssSelector) Then
            GetText = html.querySelector(childOfSiblingCssSelector).innerText
            Exit Function
        End If
    Next
    GetText = "Not found"
End Function

Public Function GetLastRow(ByVal ws As Worksheet, Optional ByVal columnNumber As Long = 1) As Long
    With ws
        GetLastRow = .Cells(.rows.Count, columnNumber).End(xlUp).Row
    End With
End Function
</code>```

Body:
The code works fine, but I need it to extract ONLY emails and URLs and place the email in Sheet1 "Scraper" NEXT BLANK ROW

Emails =  Column A
Urls =  Column B

Currently it extracts anything text, emails or URL and places them in column A or B.

I only need Emails or URLs. I have been stuck on this for sometime and can't seem to work it out

Also I am not sure if my DELETE DUPLICATES is deleting duplicate rows or duplicates in column. It SHOULD be duplicate rows.

How the code works:

On Sheet2 "URL List" I have a list of URLs, the code runs through this and places the results onto Sheet1 "Scraper". and deletes any duplicates

It is only supposed to scraper email and URLs and place them in Column A,B on NEXT BLANK ROW.

I have tried to fix the problem but it is out of my scope.

Private Sub fbStart_Click()
'Set sheet2 URL List and open Internet Explorer
    Dim lr          As Long
    Dim x           As Long
    Dim arr()       As Variant
    Dim wks         As Worksheet
    Dim ie          As Object
    Dim dd(1 To 2)  As String
    Dim Fr          As Long

    On Error Resume Next
    Application.ScreenUpdating = False

    Set wks = ThisWorkbook.Sheets("Url List")
    With wks
        Fr = .Cells(.Rows.Count, 6).End(xlUp).Offset(1).Row
        lr = .Cells(.Rows.Count, 1).End(xlUp).Row
        .Cells(1, 5).Value = lr
        arr = .Range(.Cells(Fr, 1), .Cells(lr, 1)).Value
    End With

    'Show Internet Explorer and add delay in seconds if needed
    Set ie = CreateObject("InternetExplorer.Application")
    With ie
        .Visible = True
        Application.Wait Now + TimeValue("0:00:0")

        For x = LBound(arr, 1) To UBound(arr, 1)
            .navigate arr(x, 1)
            wtime = Time
            Do While .Busy Or .readyState <> 4
                DoEvents

            'Skip pages with Captchas  + write the word Captcha in Sheet 2 Column C
                If Time > (wtime + TimeValue("00:00:10")) Then
                    Cells(x + 1, "C").Value = "Captcha"
                    Exit Do
                End If
            Loop

            On Error Resume Next
            'Variable for document or data which need to be extracted out of webpage, change innertext number if same class used
            Dim doc As HTMLDocument
            Set doc = ie.document
            dd(1) = doc.getElementsByClassName("_50f4")(2).innerText
            dd(2) = doc.getElementsByClassName("_50f4")(3).innerText

            'Paste the web data into Sheet1 "Scraper" in next BLANK ROW
            With Sheet1
                .Cells(.Rows.Count, "A").End(xlUp).Offset(1, 0).Resize(, 2).Value = dd
            End With

            ' Put A number 1 in Sheet2 "Url List"column B to notify this URL is done
            Sheets("Url List").Range("B" & Rows.Count).End(xlUp).Offset(1, 0).Value = 1

             'Deletes duplicates in column A Sheet1
            Columns(1).RemoveDuplicates Columns:=Array(1)
            Columns(2).RemoveDuplicates Columns:=Array(1)

             'Count No1 in sheet2 Column B
            With Worksheets("Url List")
                Lastrow = .Cells(.Rows.Count, "B").End(xlUp).Row
                Sheets("Url List").Range("B1").Value = Lastrow
            End With
            Call Autoclick_Click
        Next x
       .Quit
    End With

    'Hide FaceBook Scraper Form
    ScraperForm.Hide

End Sub

Body:
Below is to show you how to handle finding email and website address. You already have your loop and de-duplicate. Below are helper methods for extracting the required info. You can simply assign from the variables email and website to your cells in loop. I show a method using a helper function to determine lastRow in target sheet and writing out variables to correct columns in one go.

I can help with implementing the loop integration if needed, but the emphasis here was on explaining what could be done for identifying those elements of interest and how to write out to correct columns. Tbh - de-duplicating is so easily done in sheet at end but you can also use macro recorder to get perfectly functional code for that single step/use existing SO answers.

tl;dr;

This would be a lot easier if  :contains / :has css pseudo classes were permitted. Instead, my approach is as follows:

email - find the href attribute whose value starts with mailto

website - check that there is a website icon on the page

Specify a parent of both the website icon and the website address

Loop all matches to that parent specification checking if contains the website icon (this is where pseudo class selectors would have simplified things). If match found then we have the shared parent of both icon and hopefully website address; use childOfSiblingCssSelector (we are looking at a child of the following div in this case) css selector to extract the website url.

Notes:

The entire thing is kept quite high level/generic such that you can adjust your css selectors to hopefully cater for different scenarios. Consequence - may seem a little verbose.

Helper functions are provided to handle element matching. Name these in a way that makes sense for what they are doing. I think some room for improvement here.

Whilst technically the second helper, GetText, could be used to extract the email address (I'd probably add another argument to function call to specify attribute to extract) as well as website address, it seems far quicker, currently, to simply target the appropriate href as detailed above.

I have kept the css selectors as local variables close to their usage; you could have them as constants, closer to top of module, where easier to access perhaps? Unsure without seeing how this performs over time/different urls

Css selectors are chosen over .getElementsBy methods for two reasons: 1) there is browser optimization for css selectors so, if well formulated, css will be faster 2) I want to preserve the flexibility of the code/helper functions - you have far more specificity with css selectors in terms of what patterns you can express. I deemed this important as I don't know what future cases you may need to handle.

I am deliberately not using class name and index e.g. doc.getElementsByClassName("_50f4")(2).innerText, as I am unfamiliar with the range of potential use cases; this feels a little fragile as relies on consistent ordering and numbering of elements (at least up to these indices).

TODO:

Rather than instantiate a new HTMLDocument each time in GetText, it is more efficient to pass another  HTMLDocument argument in the function signature i.e. from calling procedure. A re-factor could take that into consideration.

This type of coding might lend itself to being class based in the future. Particularly if error handling is to be added and further functions.

VBA:

Option Explicit
'VBE > Tools > References > HTML Object Library
Public Sub test()
    Dim ie As Object, ws As Worksheet
    Set ie = CreateObject("InternetExplorer.Application")
    Set ws = ThisWorkbook.Worksheets("Scraper")

    With ie
        .Visible = True
        .Navigate2 "https://www.facebook.com/pg/SalemFordNH/about/?ref=page_internal%5Blink%5D"

        While .Busy Or .readyState < 4: DoEvents: Wend

        With .document

            Dim email As String, website As String, iconCssSelector As String
            'iconCssSelector for website icon in this instance
            iconCssSelector = "[src='https://static.xx.fbcdn.net/rsrc.php/v3/yV/r/EaDvTjOwxIV.png']"

            If ElementIsPresent(ie.document, "[href^=mailto]") Then
                email = ie.document.querySelector("[href^=mailto]").innerText
            Else
                email = "Not found"
            End If

            Dim parents As Object, sharedParentCssSelector As String, childOfSiblingCssSelector As String
            sharedParentCssSelector = "._5aj7" 'target parent of both icon and the website link
            childOfSiblingCssSelector = "._50f4" '< to target website address after finding right parent

            If ElementIsPresent(ie.document, iconCssSelector) _
                And ElementIsPresent(ie.document, sharedParentCssSelector) Then

                Set parents = ie.document.querySelectorAll(sharedParentCssSelector) 'css selector used to allow for greater flexibility in element matching
                website = GetText(ie.document, parents, iconCssSelector, childOfSiblingCssSelector)
            Else
                website = "Not found"
            End If
        End With
        'Assumes headers already present
        Dim nextRow As Long
        nextRow = GetLastRow(ws, 1) + 1
        ws.Cells(nextRow, 1).Resize(1, 2) = Array(email, website)
        .Quit
    End With
End Sub

Public Function ElementIsPresent(ByVal document As HTMLDocument, ByVal cssSelector As String) As Boolean
    ElementIsPresent = document.querySelectorAll(cssSelector).length > 0
End Function

Public Function GetText(ByVal document As HTMLDocument, ByVal parents As Object, ByVal iconCssSelector As String, ByVal childOfSiblingCssSelector As String) As String
    'in this instance and with microsoft IE DOM you cannot select for parent of an element with pseudo class _
    of :has(>child); nor use :contains... instead pass expected parent selector, that houses _
    both the icon element for website and the website address itself, and loop all matches checking for website icon _
    if found use childOfSiblingCssSelector to extract
    Dim i As Long, html As HTMLDocument
    Set html = New HTMLDocument

    For i = 0 To parents.length - 1
        html.body.innerHTML = parents.item(i).innerHTML
        If ElementIsPresent(html, iconCssSelector) Then
            GetText = html.querySelector(childOfSiblingCssSelector).innerText
            Exit Function
        End If
    Next
    GetText = "Not found"
End Function

Public Function GetLastRow(ByVal ws As Worksheet, Optional ByVal columnNumber As Long = 1) As Long
    With ws
        GetLastRow = .Cells(.rows.Count, columnNumber).End(xlUp).Row
    End With
End Function

Project references (VBE > Tools > References):

Microsoft HTML Object Library

Additional reading:

https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Selectors

https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelectorAll

https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelector

Edit:

Example of loop - assumes no empty rows in column A between urls.

Option Explicit
'VBE > Tools > References > HTML Object Library
Public Sub test()
    Dim ie As Object, ws As Worksheet, wsUrls As Worksheet, urls()
    Set ie = CreateObject("InternetExplorer.Application")
    Set ws = ThisWorkbook.Worksheets("Scraper")
    Set wsUrls = ThisWorkbook.Worksheets("Url List")

    With wsUrls
        urls = Application.Transpose(.Range("A2:A" & .Cells(.rows.Count, "A").End(xlUp).Row).Value)
    End With
    Dim results(), r As Long
    ReDim results(1 To UBound(urls), 1 To 2)

    With ie
        .Visible = True

        For r = LBound(urls) To UBound(urls)
            .Navigate2 urls(r)

            While .Busy Or .readyState < 4: DoEvents: Wend

            With .document

                Dim email As String, website As String, iconCssSelector As String
                'iconCssSelector for website icon in this instance
                iconCssSelector = "[src='https://static.xx.fbcdn.net/rsrc.php/v3/yV/r/EaDvTjOwxIV.png']"

                If ElementIsPresent(ie.document, "[href^=mailto]") Then
                    email = ie.document.querySelector("[href^=mailto]").innerText
                Else
                    email = "Not found"
                End If

                Dim parents As Object, sharedParentCssSelector As String, childOfSiblingCssSelector As String
                sharedParentCssSelector = "._5aj7" 'target parent of both icon and the website link
                childOfSiblingCssSelector = "._50f4" '< to target website address after finding right parent

                If ElementIsPresent(ie.document, iconCssSelector) _
        And ElementIsPresent(ie.document, sharedParentCssSelector) Then

                    Set parents = ie.document.querySelectorAll(sharedParentCssSelector) 'css selector used to allow for greater flexibility in element matching
                    website = GetText(ie.document, parents, iconCssSelector, childOfSiblingCssSelector)
                Else
                    website = "Not found"
                End If
            End With
            'Assumes headers already present
            Dim nextRow As Long
            results(r, 1) = email
            results(r, 2) = website
        Next
        .Quit
    End With
    nextRow = GetLastRow(ws, 1) + 1
    ws.Cells(nextRow, 1).Resize(UBound(results, 1), UBound(results, 2)) = results
End Sub

Public Function ElementIsPresent(ByVal document As HTMLDocument, ByVal cssSelector As String) As Boolean
    ElementIsPresent = document.querySelectorAll(cssSelector).length > 0
End Function

Public Function GetText(ByVal document As HTMLDocument, ByVal parents As Object, ByVal iconCssSelector As String, ByVal childOfSiblingCssSelector As String) As String
    'in this instance and with microsoft IE DOM you cannot select for parent of an element with pseudo class _
    of :has(>child); nor use :contains... instead pass expected parent selector, that houses _
    both the icon element for website and the website address itself, and loop all matches checking for website icon _
    if found use childOfSiblingCssSelector to extract
    Dim i As Long, html As HTMLDocument
    Set html = New HTMLDocument

    For i = 0 To parents.length - 1
        html.body.innerHTML = parents.item(i).innerHTML
        If ElementIsPresent(html, iconCssSelector) Then
            GetText = html.querySelector(childOfSiblingCssSelector).innerText
            Exit Function
        End If
    Next
    GetText = "Not found"
End Function

Public Function GetLastRow(ByVal ws As Worksheet, Optional ByVal columnNumber As Long = 1) As Long
    With ws
        GetLastRow = .Cells(.rows.Count, columnNumber).End(xlUp).Row
    End With
End Function